Revision 2364
Added by Jean-Philippe Lang over 16 years ago
sandbox/rails-2.2/config/boot.rb | ||
---|---|---|
67 | 67 |
|
68 | 68 |
class << self |
69 | 69 |
def rubygems_version |
70 |
Gem::RubyGemsVersion if defined? Gem::RubyGemsVersion
|
|
70 |
Gem::RubyGemsVersion rescue nil
|
|
71 | 71 |
end |
72 | 72 |
|
73 | 73 |
def gem_version |
... | ... | |
82 | 82 |
|
83 | 83 |
def load_rubygems |
84 | 84 |
require 'rubygems' |
85 |
|
|
86 |
unless rubygems_version >= '0.9.4'
|
|
87 |
$stderr.puts %(Rails requires RubyGems >= 0.9.4 (you have #{rubygems_version}). Please `gem update --system` and try again.)
|
|
85 |
min_version = '1.3.1' |
|
86 |
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 | 88 |
exit 1 |
89 | 89 |
end |
90 | 90 |
|
91 | 91 |
rescue LoadError |
92 |
$stderr.puts %(Rails requires RubyGems >= 0.9.4. Please install RubyGems and try again: http://rubygems.rubyforge.org)
|
|
92 |
$stderr.puts %Q(Rails requires RubyGems >= #{min_version}. Please install RubyGems and try again: http://rubygems.rubyforge.org)
|
|
93 | 93 |
exit 1 |
94 | 94 |
end |
95 | 95 |
|
sandbox/rails-2.2/config/environment.rb | ||
---|---|---|
5 | 5 |
# ENV['RAILS_ENV'] ||= 'production' |
6 | 6 |
|
7 | 7 |
# Specifies gem version of Rails to use when vendor/rails is not present |
8 |
RAILS_GEM_VERSION = '2.1.2' unless defined? RAILS_GEM_VERSION
|
|
8 |
RAILS_GEM_VERSION = '2.2.2' unless defined? RAILS_GEM_VERSION
|
|
9 | 9 |
|
10 | 10 |
# Bootstrap the Rails environment, frameworks, and default configuration |
11 | 11 |
require File.join(File.dirname(__FILE__), 'boot') |
sandbox/rails-2.2/public/javascripts/controls.js | ||
---|---|---|
1 | 1 |
// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) |
2 |
// (c) 2005-2007 Ivan Krstic (http://blogs.law.harvard.edu/ivan)
|
|
3 |
// (c) 2005-2007 Jon Tirsen (http://www.tirsen.com)
|
|
2 |
// (c) 2005-2008 Ivan Krstic (http://blogs.law.harvard.edu/ivan)
|
|
3 |
// (c) 2005-2008 Jon Tirsen (http://www.tirsen.com)
|
|
4 | 4 |
// Contributors: |
5 | 5 |
// Richard Livsey |
6 | 6 |
// Rahul Bhargava |
7 | 7 |
// Rob Wills |
8 |
//
|
|
8 |
// |
|
9 | 9 |
// script.aculo.us is freely distributable under the terms of an MIT-style license. |
10 | 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 | 13 |
// that's independent of the data source for autocompletion. This |
14 | 14 |
// includes drawing the autocompletion menu, observing keyboard |
15 | 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 | 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 | 20 |
// should get the text for which to provide autocompletion by |
21 | 21 |
// invoking this.getToken(), NOT by directly accessing |
22 | 22 |
// this.element.value. This is to allow incremental tokenized |
... | ... | |
30 | 30 |
// will incrementally autocomplete with a comma as the token. |
31 | 31 |
// Additionally, ',' in the above example can be replaced with |
32 | 32 |
// a token array, e.g. { tokens: [',', '\n'] } which |
33 |
// enables autocompletion on multiple tokens. This is most
|
|
34 |
// useful when one of the tokens is \n (a newline), as it
|
|
33 |
// enables autocompletion on multiple tokens. This is most |
|
34 |
// useful when one of the tokens is \n (a newline), as it |
|
35 | 35 |
// allows smart autocompletion after linebreaks. |
36 | 36 |
|
37 | 37 |
if(typeof Effect == 'undefined') |
38 | 38 |
throw("controls.js requires including script.aculo.us' effects.js library"); |
39 | 39 |
|
40 |
var Autocompleter = { } |
|
40 |
var Autocompleter = { };
|
|
41 | 41 |
Autocompleter.Base = Class.create({ |
42 | 42 |
baseInitialize: function(element, update, options) { |
43 |
element = $(element) |
|
44 |
this.element = element;
|
|
45 |
this.update = $(update);
|
|
46 |
this.hasFocus = false;
|
|
47 |
this.changed = false;
|
|
48 |
this.active = false;
|
|
49 |
this.index = 0;
|
|
43 |
element = $(element);
|
|
44 |
this.element = element; |
|
45 |
this.update = $(update); |
|
46 |
this.hasFocus = false; |
|
47 |
this.changed = false; |
|
48 |
this.active = false; |
|
49 |
this.index = 0; |
|
50 | 50 |
this.entryCount = 0; |
51 | 51 |
this.oldElementValue = this.element.value; |
52 | 52 |
|
... | ... | |
59 | 59 |
this.options.tokens = this.options.tokens || []; |
60 | 60 |
this.options.frequency = this.options.frequency || 0.4; |
61 | 61 |
this.options.minChars = this.options.minChars || 1; |
62 |
this.options.onShow = this.options.onShow ||
|
|
63 |
function(element, update){
|
|
62 |
this.options.onShow = this.options.onShow || |
|
63 |
function(element, update){ |
|
64 | 64 |
if(!update.style.position || update.style.position=='absolute') { |
65 | 65 |
update.style.position = 'absolute'; |
66 | 66 |
Position.clone(element, update, { |
67 |
setHeight: false,
|
|
67 |
setHeight: false, |
|
68 | 68 |
offsetTop: element.offsetHeight |
69 | 69 |
}); |
70 | 70 |
} |
71 | 71 |
Effect.Appear(update,{duration:0.15}); |
72 | 72 |
}; |
73 |
this.options.onHide = this.options.onHide ||
|
|
73 |
this.options.onHide = this.options.onHide || |
|
74 | 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 | 77 |
this.options.tokens = new Array(this.options.tokens); |
78 | 78 |
// Force carriage returns as token delimiters anyway |
79 | 79 |
if (!this.options.tokens.include('\n')) |
80 | 80 |
this.options.tokens.push('\n'); |
81 | 81 |
|
82 | 82 |
this.observer = null; |
83 |
|
|
83 |
|
|
84 | 84 |
this.element.setAttribute('autocomplete','off'); |
85 | 85 |
|
86 | 86 |
Element.hide(this.update); |
... | ... | |
91 | 91 |
|
92 | 92 |
show: function() { |
93 | 93 |
if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update); |
94 |
if(!this.iefix &&
|
|
94 |
if(!this.iefix && |
|
95 | 95 |
(Prototype.Browser.IE) && |
96 | 96 |
(Element.getStyle(this.update, 'position')=='absolute')) { |
97 |
new Insertion.After(this.update,
|
|
97 |
new Insertion.After(this.update, |
|
98 | 98 |
'<iframe id="' + this.update.id + '_iefix" '+ |
99 | 99 |
'style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" ' + |
100 | 100 |
'src="javascript:false;" frameborder="0" scrolling="no"></iframe>'); |
... | ... | |
102 | 102 |
} |
103 | 103 |
if(this.iefix) setTimeout(this.fixIEOverlapping.bind(this), 50); |
104 | 104 |
}, |
105 |
|
|
105 |
|
|
106 | 106 |
fixIEOverlapping: function() { |
107 | 107 |
Position.clone(this.update, this.iefix, {setTop:(!this.update.style.height)}); |
108 | 108 |
this.iefix.style.zIndex = 1; |
... | ... | |
150 | 150 |
Event.stop(event); |
151 | 151 |
return; |
152 | 152 |
} |
153 |
else
|
|
154 |
if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN ||
|
|
153 |
else |
|
154 |
if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN || |
|
155 | 155 |
(Prototype.Browser.WebKit > 0 && event.keyCode == 0)) return; |
156 | 156 |
|
157 | 157 |
this.changed = true; |
158 | 158 |
this.hasFocus = true; |
159 | 159 |
|
160 | 160 |
if(this.observer) clearTimeout(this.observer); |
161 |
this.observer =
|
|
161 |
this.observer = |
|
162 | 162 |
setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000); |
163 | 163 |
}, |
164 | 164 |
|
... | ... | |
170 | 170 |
|
171 | 171 |
onHover: function(event) { |
172 | 172 |
var element = Event.findElement(event, 'LI'); |
173 |
if(this.index != element.autocompleteIndex)
|
|
173 |
if(this.index != element.autocompleteIndex) |
|
174 | 174 |
{ |
175 | 175 |
this.index = element.autocompleteIndex; |
176 | 176 |
this.render(); |
177 | 177 |
} |
178 | 178 |
Event.stop(event); |
179 | 179 |
}, |
180 |
|
|
180 |
|
|
181 | 181 |
onClick: function(event) { |
182 | 182 |
var element = Event.findElement(event, 'LI'); |
183 | 183 |
this.index = element.autocompleteIndex; |
184 | 184 |
this.selectEntry(); |
185 | 185 |
this.hide(); |
186 | 186 |
}, |
187 |
|
|
187 |
|
|
188 | 188 |
onBlur: function(event) { |
189 | 189 |
// needed to make click events working |
190 | 190 |
setTimeout(this.hide.bind(this), 250); |
191 | 191 |
this.hasFocus = false; |
192 |
this.active = false;
|
|
193 |
},
|
|
194 |
|
|
192 |
this.active = false; |
|
193 |
}, |
|
194 |
|
|
195 | 195 |
render: function() { |
196 | 196 |
if(this.entryCount > 0) { |
197 | 197 |
for (var i = 0; i < this.entryCount; i++) |
198 |
this.index==i ?
|
|
199 |
Element.addClassName(this.getEntry(i),"selected") :
|
|
198 |
this.index==i ? |
|
199 |
Element.addClassName(this.getEntry(i),"selected") : |
|
200 | 200 |
Element.removeClassName(this.getEntry(i),"selected"); |
201 |
if(this.hasFocus) {
|
|
201 |
if(this.hasFocus) { |
|
202 | 202 |
this.show(); |
203 | 203 |
this.active = true; |
204 | 204 |
} |
... | ... | |
207 | 207 |
this.hide(); |
208 | 208 |
} |
209 | 209 |
}, |
210 |
|
|
210 |
|
|
211 | 211 |
markPrevious: function() { |
212 |
if(this.index > 0) this.index-- |
|
212 |
if(this.index > 0) this.index--;
|
|
213 | 213 |
else this.index = this.entryCount-1; |
214 | 214 |
this.getEntry(this.index).scrollIntoView(true); |
215 | 215 |
}, |
216 |
|
|
216 |
|
|
217 | 217 |
markNext: function() { |
218 |
if(this.index < this.entryCount-1) this.index++ |
|
218 |
if(this.index < this.entryCount-1) this.index++;
|
|
219 | 219 |
else this.index = 0; |
220 | 220 |
this.getEntry(this.index).scrollIntoView(false); |
221 | 221 |
}, |
222 |
|
|
222 |
|
|
223 | 223 |
getEntry: function(index) { |
224 | 224 |
return this.update.firstChild.childNodes[index]; |
225 | 225 |
}, |
226 |
|
|
226 |
|
|
227 | 227 |
getCurrentEntry: function() { |
228 | 228 |
return this.getEntry(this.index); |
229 | 229 |
}, |
230 |
|
|
230 |
|
|
231 | 231 |
selectEntry: function() { |
232 | 232 |
this.active = false; |
233 | 233 |
this.updateElement(this.getCurrentEntry()); |
... | ... | |
244 | 244 |
if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select); |
245 | 245 |
} else |
246 | 246 |
value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal'); |
247 |
|
|
247 |
|
|
248 | 248 |
var bounds = this.getTokenBounds(); |
249 | 249 |
if (bounds[0] != -1) { |
250 | 250 |
var newValue = this.element.value.substr(0, bounds[0]); |
... | ... | |
257 | 257 |
} |
258 | 258 |
this.oldElementValue = this.element.value; |
259 | 259 |
this.element.focus(); |
260 |
|
|
260 |
|
|
261 | 261 |
if (this.options.afterUpdateElement) |
262 | 262 |
this.options.afterUpdateElement(this.element, selectedElement); |
263 | 263 |
}, |
... | ... | |
269 | 269 |
Element.cleanWhitespace(this.update.down()); |
270 | 270 |
|
271 | 271 |
if(this.update.firstChild && this.update.down().childNodes) { |
272 |
this.entryCount =
|
|
272 |
this.entryCount = |
|
273 | 273 |
this.update.down().childNodes.length; |
274 | 274 |
for (var i = 0; i < this.entryCount; i++) { |
275 | 275 |
var entry = this.getEntry(i); |
276 | 276 |
entry.autocompleteIndex = i; |
277 | 277 |
this.addObservers(entry); |
278 | 278 |
} |
279 |
} else {
|
|
279 |
} else { |
|
280 | 280 |
this.entryCount = 0; |
281 | 281 |
} |
282 | 282 |
|
283 | 283 |
this.stopIndicator(); |
284 | 284 |
this.index = 0; |
285 |
|
|
285 |
|
|
286 | 286 |
if(this.entryCount==1 && this.options.autoSelect) { |
287 | 287 |
this.selectEntry(); |
288 | 288 |
this.hide(); |
... | ... | |
298 | 298 |
}, |
299 | 299 |
|
300 | 300 |
onObserverEvent: function() { |
301 |
this.changed = false;
|
|
301 |
this.changed = false; |
|
302 | 302 |
this.tokenBounds = null; |
303 | 303 |
if(this.getToken().length>=this.options.minChars) { |
304 | 304 |
this.getUpdatedChoices(); |
... | ... | |
351 | 351 |
|
352 | 352 |
getUpdatedChoices: function() { |
353 | 353 |
this.startIndicator(); |
354 |
|
|
355 |
var entry = encodeURIComponent(this.options.paramName) + '=' +
|
|
354 |
|
|
355 |
var entry = encodeURIComponent(this.options.paramName) + '=' + |
|
356 | 356 |
encodeURIComponent(this.getToken()); |
357 | 357 |
|
358 | 358 |
this.options.parameters = this.options.callback ? |
359 | 359 |
this.options.callback(this.element, entry) : entry; |
360 | 360 |
|
361 |
if(this.options.defaultParams)
|
|
361 |
if(this.options.defaultParams) |
|
362 | 362 |
this.options.parameters += '&' + this.options.defaultParams; |
363 |
|
|
363 |
|
|
364 | 364 |
new Ajax.Request(this.url, this.options); |
365 | 365 |
}, |
366 | 366 |
|
... | ... | |
382 | 382 |
// - choices - How many autocompletion choices to offer |
383 | 383 |
// |
384 | 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 | 386 |
// autocomplete array. Defaults to true, which will |
387 | 387 |
// match text at the beginning of any *word* in the |
388 | 388 |
// strings in the autocomplete array. If you want to |
... | ... | |
399 | 399 |
// - ignoreCase - Whether to ignore case when autocompleting. |
400 | 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 | 403 |
// option, if you prefer to write your own autocompletion logic. |
404 | 404 |
// In that case, the other options above will not apply unless |
405 | 405 |
// you support them. |
... | ... | |
427 | 427 |
var entry = instance.getToken(); |
428 | 428 |
var count = 0; |
429 | 429 |
|
430 |
for (var i = 0; i < instance.options.array.length &&
|
|
431 |
ret.length < instance.options.choices ; i++) {
|
|
430 |
for (var i = 0; i < instance.options.array.length && |
|
431 |
ret.length < instance.options.choices ; i++) { |
|
432 | 432 |
|
433 | 433 |
var elem = instance.options.array[i]; |
434 |
var foundPos = instance.options.ignoreCase ?
|
|
435 |
elem.toLowerCase().indexOf(entry.toLowerCase()) :
|
|
434 |
var foundPos = instance.options.ignoreCase ? |
|
435 |
elem.toLowerCase().indexOf(entry.toLowerCase()) : |
|
436 | 436 |
elem.indexOf(entry); |
437 | 437 |
|
438 | 438 |
while (foundPos != -1) { |
439 |
if (foundPos == 0 && elem.length != entry.length) {
|
|
440 |
ret.push("<li><strong>" + elem.substr(0, entry.length) + "</strong>" +
|
|
439 |
if (foundPos == 0 && elem.length != entry.length) { |
|
440 |
ret.push("<li><strong>" + elem.substr(0, entry.length) + "</strong>" + |
|
441 | 441 |
elem.substr(entry.length) + "</li>"); |
442 | 442 |
break; |
443 |
} else if (entry.length >= instance.options.partialChars &&
|
|
443 |
} else if (entry.length >= instance.options.partialChars && |
|
444 | 444 |
instance.options.partialSearch && foundPos != -1) { |
445 | 445 |
if (instance.options.fullSearch || /\s/.test(elem.substr(foundPos-1,1))) { |
446 | 446 |
partial.push("<li>" + elem.substr(0, foundPos) + "<strong>" + |
... | ... | |
450 | 450 |
} |
451 | 451 |
} |
452 | 452 |
|
453 |
foundPos = instance.options.ignoreCase ?
|
|
454 |
elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) :
|
|
453 |
foundPos = instance.options.ignoreCase ? |
|
454 |
elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) : |
|
455 | 455 |
elem.indexOf(entry, foundPos + 1); |
456 | 456 |
|
457 | 457 |
} |
458 | 458 |
} |
459 | 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 | 461 |
return "<ul>" + ret.join('') + "</ul>"; |
462 | 462 |
} |
463 | 463 |
}, options || { }); |
... | ... | |
474 | 474 |
setTimeout(function() { |
475 | 475 |
Field.activate(field); |
476 | 476 |
}, 1); |
477 |
} |
|
477 |
};
|
|
478 | 478 |
|
479 | 479 |
Ajax.InPlaceEditor = Class.create({ |
480 | 480 |
initialize: function(element, url, options) { |
... | ... | |
604 | 604 |
this.triggerCallback('onEnterHover'); |
605 | 605 |
}, |
606 | 606 |
getText: function() { |
607 |
return this.element.innerHTML; |
|
607 |
return this.element.innerHTML.unescapeHTML();
|
|
608 | 608 |
}, |
609 | 609 |
handleAJAXFailure: function(transport) { |
610 | 610 |
this.triggerCallback('onFailure', transport); |
... | ... | |
780 | 780 |
onSuccess: function(transport) { |
781 | 781 |
var js = transport.responseText.strip(); |
782 | 782 |
if (!/^\[.*\]$/.test(js)) // TODO: improve sanity check |
783 |
throw 'Server returned an invalid collection representation.';
|
|
783 |
throw('Server returned an invalid collection representation.');
|
|
784 | 784 |
this._collection = eval(js); |
785 | 785 |
this.checkForExternalText(); |
786 | 786 |
}.bind(this), |
... | ... | |
937 | 937 |
loadingCollectionText: 'Loading options...' |
938 | 938 |
}; |
939 | 939 |
|
940 |
// Delayed observer, like Form.Element.Observer,
|
|
940 |
// Delayed observer, like Form.Element.Observer, |
|
941 | 941 |
// but waits for delay after last key input |
942 | 942 |
// Ideal for live-search fields |
943 | 943 |
|
... | ... | |
947 | 947 |
this.element = $(element); |
948 | 948 |
this.callback = callback; |
949 | 949 |
this.timer = null; |
950 |
this.lastValue = $F(this.element);
|
|
950 |
this.lastValue = $F(this.element); |
|
951 | 951 |
Event.observe(this.element,'keyup',this.delayedListener.bindAsEventListener(this)); |
952 | 952 |
}, |
953 | 953 |
delayedListener: function(event) { |
... | ... | |
960 | 960 |
this.timer = null; |
961 | 961 |
this.callback(this.element, $F(this.element)); |
962 | 962 |
} |
963 |
}); |
|
963 |
}); |
sandbox/rails-2.2/public/javascripts/dragdrop.js | ||
---|---|---|
1 | 1 |
// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) |
2 |
// (c) 2005-2007 Sammi Williams (http://www.oriontransfer.co.nz, [email protected]) |
|
3 |
//
|
|
2 |
// (c) 2005-2008 Sammi Williams (http://www.oriontransfer.co.nz, [email protected]) |
|
3 |
// |
|
4 | 4 |
// script.aculo.us is freely distributable under the terms of an MIT-style license. |
5 | 5 |
// For details, see the script.aculo.us web site: http://script.aculo.us/ |
6 | 6 |
|
... | ... | |
32 | 32 |
options._containers.push($(containment)); |
33 | 33 |
} |
34 | 34 |
} |
35 |
|
|
35 |
|
|
36 | 36 |
if(options.accept) options.accept = [options.accept].flatten(); |
37 | 37 |
|
38 | 38 |
Element.makePositioned(element); // fix IE |
... | ... | |
40 | 40 |
|
41 | 41 |
this.drops.push(options); |
42 | 42 |
}, |
43 |
|
|
43 |
|
|
44 | 44 |
findDeepestChild: function(drops) { |
45 | 45 |
deepest = drops[0]; |
46 |
|
|
46 |
|
|
47 | 47 |
for (i = 1; i < drops.length; ++i) |
48 | 48 |
if (Element.isParent(drops[i].element, deepest.element)) |
49 | 49 |
deepest = drops[i]; |
50 |
|
|
50 |
|
|
51 | 51 |
return deepest; |
52 | 52 |
}, |
53 | 53 |
|
54 | 54 |
isContained: function(element, drop) { |
55 | 55 |
var containmentNode; |
56 | 56 |
if(drop.tree) { |
57 |
containmentNode = element.treeNode;
|
|
57 |
containmentNode = element.treeNode; |
|
58 | 58 |
} else { |
59 | 59 |
containmentNode = element.parentNode; |
60 | 60 |
} |
61 | 61 |
return drop._containers.detect(function(c) { return containmentNode == c }); |
62 | 62 |
}, |
63 |
|
|
63 |
|
|
64 | 64 |
isAffected: function(point, element, drop) { |
65 | 65 |
return ( |
66 | 66 |
(drop.element!=element) && |
67 | 67 |
((!drop._containers) || |
68 | 68 |
this.isContained(element, drop)) && |
69 | 69 |
((!drop.accept) || |
70 |
(Element.classNames(element).detect(
|
|
70 |
(Element.classNames(element).detect( |
|
71 | 71 |
function(v) { return drop.accept.include(v) } ) )) && |
72 | 72 |
Position.within(drop.element, point[0], point[1]) ); |
73 | 73 |
}, |
... | ... | |
87 | 87 |
show: function(point, element) { |
88 | 88 |
if(!this.drops.length) return; |
89 | 89 |
var drop, affected = []; |
90 |
|
|
90 |
|
|
91 | 91 |
this.drops.each( function(drop) { |
92 | 92 |
if(Droppables.isAffected(point, element, drop)) |
93 | 93 |
affected.push(drop); |
94 | 94 |
}); |
95 |
|
|
95 |
|
|
96 | 96 |
if(affected.length>0) |
97 | 97 |
drop = Droppables.findDeepestChild(affected); |
98 | 98 |
|
... | ... | |
101 | 101 |
Position.within(drop.element, point[0], point[1]); |
102 | 102 |
if(drop.onHover) |
103 | 103 |
drop.onHover(element, drop.element, Position.overlap(drop.overlap, drop.element)); |
104 |
|
|
104 |
|
|
105 | 105 |
if (drop != this.last_active) Droppables.activate(drop); |
106 | 106 |
} |
107 | 107 |
}, |
... | ... | |
112 | 112 |
|
113 | 113 |
if (this.isAffected([Event.pointerX(event), Event.pointerY(event)], element, this.last_active)) |
114 | 114 |
if (this.last_active.onDrop) { |
115 |
this.last_active.onDrop(element, this.last_active.element, event);
|
|
116 |
return true;
|
|
115 |
this.last_active.onDrop(element, this.last_active.element, event); |
|
116 |
return true; |
|
117 | 117 |
} |
118 | 118 |
}, |
119 | 119 |
|
... | ... | |
121 | 121 |
if(this.last_active) |
122 | 122 |
this.deactivate(this.last_active); |
123 | 123 |
} |
124 |
} |
|
124 |
};
|
|
125 | 125 |
|
126 | 126 |
var Draggables = { |
127 | 127 |
drags: [], |
128 | 128 |
observers: [], |
129 |
|
|
129 |
|
|
130 | 130 |
register: function(draggable) { |
131 | 131 |
if(this.drags.length == 0) { |
132 | 132 |
this.eventMouseUp = this.endDrag.bindAsEventListener(this); |
133 | 133 |
this.eventMouseMove = this.updateDrag.bindAsEventListener(this); |
134 | 134 |
this.eventKeypress = this.keyPress.bindAsEventListener(this); |
135 |
|
|
135 |
|
|
136 | 136 |
Event.observe(document, "mouseup", this.eventMouseUp); |
137 | 137 |
Event.observe(document, "mousemove", this.eventMouseMove); |
138 | 138 |
Event.observe(document, "keypress", this.eventKeypress); |
139 | 139 |
} |
140 | 140 |
this.drags.push(draggable); |
141 | 141 |
}, |
142 |
|
|
142 |
|
|
143 | 143 |
unregister: function(draggable) { |
144 | 144 |
this.drags = this.drags.reject(function(d) { return d==draggable }); |
145 | 145 |
if(this.drags.length == 0) { |
... | ... | |
148 | 148 |
Event.stopObserving(document, "keypress", this.eventKeypress); |
149 | 149 |
} |
150 | 150 |
}, |
151 |
|
|
151 |
|
|
152 | 152 |
activate: function(draggable) { |
153 |
if(draggable.options.delay) {
|
|
154 |
this._timeout = setTimeout(function() {
|
|
155 |
Draggables._timeout = null;
|
|
156 |
window.focus();
|
|
157 |
Draggables.activeDraggable = draggable;
|
|
158 |
}.bind(this), draggable.options.delay);
|
|
153 |
if(draggable.options.delay) { |
|
154 |
this._timeout = setTimeout(function() { |
|
155 |
Draggables._timeout = null; |
|
156 |
window.focus(); |
|
157 |
Draggables.activeDraggable = draggable; |
|
158 |
}.bind(this), draggable.options.delay); |
|
159 | 159 |
} else { |
160 | 160 |
window.focus(); // allows keypress events if window isn't currently focused, fails for Safari |
161 | 161 |
this.activeDraggable = draggable; |
162 | 162 |
} |
163 | 163 |
}, |
164 |
|
|
164 |
|
|
165 | 165 |
deactivate: function() { |
166 | 166 |
this.activeDraggable = null; |
167 | 167 |
}, |
168 |
|
|
168 |
|
|
169 | 169 |
updateDrag: function(event) { |
170 | 170 |
if(!this.activeDraggable) return; |
171 | 171 |
var pointer = [Event.pointerX(event), Event.pointerY(event)]; |
... | ... | |
173 | 173 |
// the same coordinates, prevent needless redrawing (moz bug?) |
174 | 174 |
if(this._lastPointer && (this._lastPointer.inspect() == pointer.inspect())) return; |
175 | 175 |
this._lastPointer = pointer; |
176 |
|
|
176 |
|
|
177 | 177 |
this.activeDraggable.updateDrag(event, pointer); |
178 | 178 |
}, |
179 |
|
|
179 |
|
|
180 | 180 |
endDrag: function(event) { |
181 |
if(this._timeout) {
|
|
182 |
clearTimeout(this._timeout);
|
|
183 |
this._timeout = null;
|
|
181 |
if(this._timeout) { |
|
182 |
clearTimeout(this._timeout); |
|
183 |
this._timeout = null; |
|
184 | 184 |
} |
185 | 185 |
if(!this.activeDraggable) return; |
186 | 186 |
this._lastPointer = null; |
187 | 187 |
this.activeDraggable.endDrag(event); |
188 | 188 |
this.activeDraggable = null; |
189 | 189 |
}, |
190 |
|
|
190 |
|
|
191 | 191 |
keyPress: function(event) { |
192 | 192 |
if(this.activeDraggable) |
193 | 193 |
this.activeDraggable.keyPress(event); |
194 | 194 |
}, |
195 |
|
|
195 |
|
|
196 | 196 |
addObserver: function(observer) { |
197 | 197 |
this.observers.push(observer); |
198 | 198 |
this._cacheObserverCallbacks(); |
199 | 199 |
}, |
200 |
|
|
200 |
|
|
201 | 201 |
removeObserver: function(element) { // element instead of observer fixes mem leaks |
202 | 202 |
this.observers = this.observers.reject( function(o) { return o.element==element }); |
203 | 203 |
this._cacheObserverCallbacks(); |
204 | 204 |
}, |
205 |
|
|
205 |
|
|
206 | 206 |
notify: function(eventName, draggable, event) { // 'onStart', 'onEnd', 'onDrag' |
207 | 207 |
if(this[eventName+'Count'] > 0) |
208 | 208 |
this.observers.each( function(o) { |
... | ... | |
210 | 210 |
}); |
211 | 211 |
if(draggable.options[eventName]) draggable.options[eventName](draggable, event); |
212 | 212 |
}, |
213 |
|
|
213 |
|
|
214 | 214 |
_cacheObserverCallbacks: function() { |
215 | 215 |
['onStart','onEnd','onDrag'].each( function(eventName) { |
216 | 216 |
Draggables[eventName+'Count'] = Draggables.observers.select( |
... | ... | |
218 | 218 |
).length; |
219 | 219 |
}); |
220 | 220 |
} |
221 |
} |
|
221 |
};
|
|
222 | 222 |
|
223 | 223 |
/*--------------------------------------------------------------------------*/ |
224 | 224 |
|
... | ... | |
234 | 234 |
}, |
235 | 235 |
endeffect: function(element) { |
236 | 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 | 238 |
queue: {scope:'_draggable', position:'end'}, |
239 |
afterFinish: function(){
|
|
240 |
Draggable._dragging[element] = false
|
|
239 |
afterFinish: function(){ |
|
240 |
Draggable._dragging[element] = false |
|
241 | 241 |
} |
242 |
});
|
|
242 |
}); |
|
243 | 243 |
}, |
244 | 244 |
zindex: 1000, |
245 | 245 |
revert: false, |
... | ... | |
250 | 250 |
snap: false, // false, or xy or [x,y] or function(x,y){ return [x,y] } |
251 | 251 |
delay: 0 |
252 | 252 |
}; |
253 |
|
|
253 |
|
|
254 | 254 |
if(!arguments[1] || Object.isUndefined(arguments[1].endeffect)) |
255 | 255 |
Object.extend(defaults, { |
256 | 256 |
starteffect: function(element) { |
257 | 257 |
element._opacity = Element.getOpacity(element); |
258 | 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 | 263 |
var options = Object.extend(defaults, arguments[1] || { }); |
264 | 264 |
|
265 | 265 |
this.element = $(element); |
266 |
|
|
266 |
|
|
267 | 267 |
if(options.handle && Object.isString(options.handle)) |
268 | 268 |
this.handle = this.element.down('.'+options.handle, 0); |
269 |
|
|
269 |
|
|
270 | 270 |
if(!this.handle) this.handle = $(options.handle); |
271 | 271 |
if(!this.handle) this.handle = this.element; |
272 |
|
|
272 |
|
|
273 | 273 |
if(options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML) { |
274 | 274 |
options.scroll = $(options.scroll); |
275 | 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 | 280 |
this.options = options; |
281 |
this.dragging = false;
|
|
281 |
this.dragging = false; |
|
282 | 282 |
|
283 | 283 |
this.eventMouseDown = this.initDrag.bindAsEventListener(this); |
284 | 284 |
Event.observe(this.handle, "mousedown", this.eventMouseDown); |
285 |
|
|
285 |
|
|
286 | 286 |
Draggables.register(this); |
287 | 287 |
}, |
288 |
|
|
288 |
|
|
289 | 289 |
destroy: function() { |
290 | 290 |
Event.stopObserving(this.handle, "mousedown", this.eventMouseDown); |
291 | 291 |
Draggables.unregister(this); |
292 | 292 |
}, |
293 |
|
|
293 |
|
|
294 | 294 |
currentDelta: function() { |
295 | 295 |
return([ |
296 | 296 |
parseInt(Element.getStyle(this.element,'left') || '0'), |
297 | 297 |
parseInt(Element.getStyle(this.element,'top') || '0')]); |
298 | 298 |
}, |
299 |
|
|
299 |
|
|
300 | 300 |
initDrag: function(event) { |
301 | 301 |
if(!Object.isUndefined(Draggable._dragging[this.element]) && |
302 | 302 |
Draggable._dragging[this.element]) return; |
303 |
if(Event.isLeftClick(event)) {
|
|
303 |
if(Event.isLeftClick(event)) { |
|
304 | 304 |
// abort on form elements, fixes a Firefox issue |
305 | 305 |
var src = Event.element(event); |
306 | 306 |
if((tag_name = src.tagName.toUpperCase()) && ( |
... | ... | |
309 | 309 |
tag_name=='OPTION' || |
310 | 310 |
tag_name=='BUTTON' || |
311 | 311 |
tag_name=='TEXTAREA')) return; |
312 |
|
|
312 |
|
|
313 | 313 |
var pointer = [Event.pointerX(event), Event.pointerY(event)]; |
314 | 314 |
var pos = Position.cumulativeOffset(this.element); |
315 | 315 |
this.offset = [0,1].map( function(i) { return (pointer[i] - pos[i]) }); |
316 |
|
|
316 |
|
|
317 | 317 |
Draggables.activate(this); |
318 | 318 |
Event.stop(event); |
319 | 319 |
} |
320 | 320 |
}, |
321 |
|
|
321 |
|
|
322 | 322 |
startDrag: function(event) { |
323 | 323 |
this.dragging = true; |
324 | 324 |
if(!this.delta) |
325 | 325 |
this.delta = this.currentDelta(); |
326 |
|
|
326 |
|
|
327 | 327 |
if(this.options.zindex) { |
328 | 328 |
this.originalZ = parseInt(Element.getStyle(this.element,'z-index') || 0); |
329 | 329 |
this.element.style.zIndex = this.options.zindex; |
330 | 330 |
} |
331 |
|
|
331 |
|
|
332 | 332 |
if(this.options.ghosting) { |
333 | 333 |
this._clone = this.element.cloneNode(true); |
334 |
this.element._originallyAbsolute = (this.element.getStyle('position') == 'absolute');
|
|
335 |
if (!this.element._originallyAbsolute)
|
|
334 |
this._originallyAbsolute = (this.element.getStyle('position') == 'absolute'); |
|
335 |
if (!this._originallyAbsolute) |
|
336 | 336 |
Position.absolutize(this.element); |
337 | 337 |
this.element.parentNode.insertBefore(this._clone, this.element); |
338 | 338 |
} |
339 |
|
|
339 |
|
|
340 | 340 |
if(this.options.scroll) { |
341 | 341 |
if (this.options.scroll == window) { |
342 | 342 |
var where = this._getWindowScroll(this.options.scroll); |
... | ... | |
347 | 347 |
this.originalScrollTop = this.options.scroll.scrollTop; |
348 | 348 |
} |
349 | 349 |
} |
350 |
|
|
350 |
|
|
351 | 351 |
Draggables.notify('onStart', this, event); |
352 |
|
|
352 |
|
|
353 | 353 |
if(this.options.starteffect) this.options.starteffect(this.element); |
354 | 354 |
}, |
355 |
|
|
355 |
|
|
356 | 356 |
updateDrag: function(event, pointer) { |
357 | 357 |
if(!this.dragging) this.startDrag(event); |
358 |
|
|
358 |
|
|
359 | 359 |
if(!this.options.quiet){ |
360 | 360 |
Position.prepare(); |
361 | 361 |
Droppables.show(pointer, this.element); |
362 | 362 |
} |
363 |
|
|
363 |
|
|
364 | 364 |
Draggables.notify('onDrag', this, event); |
365 |
|
|
365 |
|
|
366 | 366 |
this.draw(pointer); |
367 | 367 |
if(this.options.change) this.options.change(this); |
368 |
|
|
368 |
|
|
369 | 369 |
if(this.options.scroll) { |
370 | 370 |
this.stopScrolling(); |
371 |
|
|
371 |
|
|
372 | 372 |
var p; |
373 | 373 |
if (this.options.scroll == window) { |
374 | 374 |
with(this._getWindowScroll(this.options.scroll)) { p = [ left, top, left+width, top+height ]; } |
... | ... | |
386 | 386 |
if(pointer[1] > (p[3]-this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[3]-this.options.scrollSensitivity); |
387 | 387 |
this.startScrolling(speed); |
388 | 388 |
} |
389 |
|
|
389 |
|
|
390 | 390 |
// fix AppleWebKit rendering |
391 | 391 |
if(Prototype.Browser.WebKit) window.scrollBy(0,0); |
392 |
|
|
392 |
|
|
393 | 393 |
Event.stop(event); |
394 | 394 |
}, |
395 |
|
|
395 |
|
|
396 | 396 |
finishDrag: function(event, success) { |
397 | 397 |
this.dragging = false; |
398 |
|
|
398 |
|
|
399 | 399 |
if(this.options.quiet){ |
400 | 400 |
Position.prepare(); |
401 | 401 |
var pointer = [Event.pointerX(event), Event.pointerY(event)]; |
... | ... | |
403 | 403 |
} |
404 | 404 |
|
405 | 405 |
if(this.options.ghosting) { |
406 |
if (!this.element._originallyAbsolute)
|
|
406 |
if (!this._originallyAbsolute) |
|
407 | 407 |
Position.relativize(this.element); |
408 |
delete this.element._originallyAbsolute;
|
|
408 |
delete this._originallyAbsolute; |
|
409 | 409 |
Element.remove(this._clone); |
410 | 410 |
this._clone = null; |
411 | 411 |
} |
412 | 412 |
|
413 |
var dropped = false;
|
|
414 |
if(success) {
|
|
415 |
dropped = Droppables.fire(event, this.element);
|
|
416 |
if (!dropped) dropped = false;
|
|
413 |
var dropped = false; |
|
414 |
if(success) { |
|
415 |
dropped = Droppables.fire(event, this.element); |
|
416 |
if (!dropped) dropped = false; |
|
417 | 417 |
} |
418 | 418 |
if(dropped && this.options.onDropped) this.options.onDropped(this.element); |
419 | 419 |
Draggables.notify('onEnd', this, event); |
420 | 420 |
|
421 | 421 |
var revert = this.options.revert; |
422 | 422 |
if(revert && Object.isFunction(revert)) revert = revert(this.element); |
423 |
|
|
423 |
|
|
424 | 424 |
var d = this.currentDelta(); |
425 | 425 |
if(revert && this.options.reverteffect) { |
426 | 426 |
if (dropped == 0 || revert != 'failure') |
... | ... | |
433 | 433 |
if(this.options.zindex) |
434 | 434 |
this.element.style.zIndex = this.originalZ; |
435 | 435 |
|
436 |
if(this.options.endeffect)
|
|
436 |
if(this.options.endeffect) |
|
437 | 437 |
this.options.endeffect(this.element); |
438 |
|
|
438 |
|
|
439 | 439 |
Draggables.deactivate(this); |
440 | 440 |
Droppables.reset(); |
441 | 441 |
}, |
442 |
|
|
442 |
|
|
443 | 443 |
keyPress: function(event) { |
444 | 444 |
if(event.keyCode!=Event.KEY_ESC) return; |
445 | 445 |
this.finishDrag(event, false); |
446 | 446 |
Event.stop(event); |
447 | 447 |
}, |
448 |
|
|
448 |
|
|
449 | 449 |
endDrag: function(event) { |
450 | 450 |
if(!this.dragging) return; |
451 | 451 |
this.stopScrolling(); |
452 | 452 |
this.finishDrag(event, true); |
453 | 453 |
Event.stop(event); |
454 | 454 |
}, |
455 |
|
|
455 |
|
|
456 | 456 |
draw: function(point) { |
457 | 457 |
var pos = Position.cumulativeOffset(this.element); |
458 | 458 |
if(this.options.ghosting) { |
459 | 459 |
var r = Position.realOffset(this.element); |
460 | 460 |
pos[0] += r[0] - Position.deltaX; pos[1] += r[1] - Position.deltaY; |
461 | 461 |
} |
462 |
|
|
462 |
|
|
463 | 463 |
var d = this.currentDelta(); |
464 | 464 |
pos[0] -= d[0]; pos[1] -= d[1]; |
465 |
|
|
465 |
|
|
466 | 466 |
if(this.options.scroll && (this.options.scroll != window && this._isScrollChild)) { |
467 | 467 |
pos[0] -= this.options.scroll.scrollLeft-this.originalScrollLeft; |
468 | 468 |
pos[1] -= this.options.scroll.scrollTop-this.originalScrollTop; |
469 | 469 |
} |
470 |
|
|
471 |
var p = [0,1].map(function(i){
|
|
472 |
return (point[i]-pos[i]-this.offset[i])
|
|
470 |
|
|
471 |
var p = [0,1].map(function(i){ |
|
472 |
return (point[i]-pos[i]-this.offset[i]) |
|
473 | 473 |
}.bind(this)); |
474 |
|
|
474 |
|
|
475 | 475 |
if(this.options.snap) { |
476 | 476 |
if(Object.isFunction(this.options.snap)) { |
477 | 477 |
p = this.options.snap(p[0],p[1],this); |
478 | 478 |
} else { |
479 | 479 |
if(Object.isArray(this.options.snap)) { |
480 | 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 | 482 |
} else { |
483 | 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 | 488 |
var style = this.element.style; |
489 | 489 |
if((!this.options.constraint) || (this.options.constraint=='horizontal')) |
490 | 490 |
style.left = p[0] + "px"; |
491 | 491 |
if((!this.options.constraint) || (this.options.constraint=='vertical')) |
492 | 492 |
style.top = p[1] + "px"; |
493 |
|
|
493 |
|
|
494 | 494 |
if(style.visibility=="hidden") style.visibility = ""; // fix gecko rendering |
495 | 495 |
}, |
496 |
|
|
496 |
|
|
497 | 497 |
stopScrolling: function() { |
498 | 498 |
if(this.scrollInterval) { |
499 | 499 |
clearInterval(this.scrollInterval); |
... | ... | |
501 | 501 |
Draggables._lastScrollPointer = null; |
502 | 502 |
} |
503 | 503 |
}, |
504 |
|
|
504 |
|
|
505 | 505 |
startScrolling: function(speed) { |
506 | 506 |
if(!(speed[0] || speed[1])) return; |
507 | 507 |
this.scrollSpeed = [speed[0]*this.options.scrollSpeed,speed[1]*this.options.scrollSpeed]; |
508 | 508 |
this.lastScrolled = new Date(); |
509 | 509 |
this.scrollInterval = setInterval(this.scroll.bind(this), 10); |
510 | 510 |
}, |
511 |
|
|
511 |
|
|
512 | 512 |
scroll: function() { |
513 | 513 |
var current = new Date(); |
514 | 514 |
var delta = current - this.lastScrolled; |
... | ... | |
524 | 524 |
this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000; |
525 | 525 |
this.options.scroll.scrollTop += this.scrollSpeed[1] * delta / 1000; |
526 | 526 |
} |
527 |
|
|
527 |
|
|
528 | 528 |
Position.prepare(); |
529 | 529 |
Droppables.show(Draggables._lastPointer, this.element); |
530 | 530 |
Draggables.notify('onDrag', this); |
... | ... | |
538 | 538 |
Draggables._lastScrollPointer[1] = 0; |
539 | 539 |
this.draw(Draggables._lastScrollPointer); |
540 | 540 |
} |
541 |
|
|
541 |
|
|
542 | 542 |
if(this.options.change) this.options.change(this); |
543 | 543 |
}, |
544 |
|
|
544 |
|
|
545 | 545 |
_getWindowScroll: function(w) { |
546 | 546 |
var T, L, W, H; |
547 | 547 |
with (w.document) { |
... | ... | |
560 | 560 |
H = documentElement.clientHeight; |
561 | 561 |
} else { |
562 | 562 |
W = body.offsetWidth; |
563 |
H = body.offsetHeight |
|
563 |
H = body.offsetHeight;
|
|
564 | 564 |
} |
565 | 565 |
} |
566 | 566 |
return { top: T, left: L, width: W, height: H }; |
... | ... | |
577 | 577 |
this.observer = observer; |
578 | 578 |
this.lastValue = Sortable.serialize(this.element); |
579 | 579 |
}, |
580 |
|
|
580 |
|
|
581 | 581 |
onStart: function() { |
582 | 582 |
this.lastValue = Sortable.serialize(this.element); |
583 | 583 |
}, |
584 |
|
|
584 |
|
|
585 | 585 |
onEnd: function() { |
586 | 586 |
Sortable.unmark(); |
587 | 587 |
if(this.lastValue != Sortable.serialize(this.element)) |
... | ... | |
591 | 591 |
|
592 | 592 |
var Sortable = { |
593 | 593 |
SERIALIZE_RULE: /^[^_\-](?:[A-Za-z0-9\-\_]*)[_](.*)$/, |
594 |
|
|
594 |
|
|
595 | 595 |
sortables: { }, |
596 |
|
|
596 |
|
|
597 | 597 |
_findRootElement: function(element) { |
598 |
while (element.tagName.toUpperCase() != "BODY") {
|
|
598 |
while (element.tagName.toUpperCase() != "BODY") { |
|
599 | 599 |
if(element.id && Sortable.sortables[element.id]) return element; |
600 | 600 |
element = element.parentNode; |
601 | 601 |
} |
... | ... | |
606 | 606 |
if(!element) return; |
607 | 607 |
return Sortable.sortables[element.id]; |
608 | 608 |
}, |
609 |
|
|
609 |
|
|
610 | 610 |
destroy: function(element){ |
611 |
var s = Sortable.options(element); |
|
612 |
|
|
611 |
element = $(element); |
|
612 |
var s = Sortable.sortables[element.id]; |
|
613 |
|
|
613 | 614 |
if(s) { |
614 | 615 |
Draggables.removeObserver(s.element); |
615 | 616 |
s.droppables.each(function(d){ Droppables.remove(d) }); |
616 | 617 |
s.draggables.invoke('destroy'); |
617 |
|
|
618 |
|
|
618 | 619 |
delete Sortable.sortables[s.element.id]; |
619 | 620 |
} |
620 | 621 |
}, |
621 | 622 |
|
622 | 623 |
create: function(element) { |
623 | 624 |
element = $(element); |
624 |
var options = Object.extend({
|
|
625 |
var options = Object.extend({ |
|
625 | 626 |
element: element, |
626 | 627 |
tag: 'li', // assumes li children, override with tag: 'tagname' |
627 | 628 |
dropOnEmpty: false, |
... | ... | |
635 | 636 |
delay: 0, |
636 | 637 |
hoverclass: null, |
637 | 638 |
ghosting: false, |
638 |
quiet: false,
|
|
639 |
quiet: false, |
|
639 | 640 |
scroll: false, |
640 | 641 |
scrollSensitivity: 20, |
641 | 642 |
scrollSpeed: 15, |
642 | 643 |
format: this.SERIALIZE_RULE, |
643 |
|
|
644 |
// these take arrays of elements or ids and can be
|
|
644 |
|
|
645 |
// these take arrays of elements or ids and can be |
|
645 | 646 |
// used for better initialization performance |
646 | 647 |
elements: false, |
647 | 648 |
handles: false, |
648 |
|
|
649 |
|
|
649 | 650 |
onChange: Prototype.emptyFunction, |
650 | 651 |
onUpdate: Prototype.emptyFunction |
651 | 652 |
}, arguments[1] || { }); |
... | ... | |
682 | 683 |
if(options.zindex) |
683 | 684 |
options_for_draggable.zindex = options.zindex; |
684 | 685 |
|
685 |
// build options for the droppables
|
|
686 |
// build options for the droppables |
|
686 | 687 |
var options_for_droppable = { |
687 | 688 |
overlap: options.overlap, |
688 | 689 |
containment: options.containment, |
689 | 690 |
tree: options.tree, |
690 | 691 |
hoverclass: options.hoverclass, |
691 | 692 |
onHover: Sortable.onHover |
692 |
} |
|
693 |
|
|
693 |
};
|
|
694 |
|
|
694 | 695 |
var options_for_tree = { |
695 | 696 |
onHover: Sortable.onEmptyHover, |
696 | 697 |
overlap: options.overlap, |
697 | 698 |
containment: options.containment, |
698 | 699 |
hoverclass: options.hoverclass |
699 |
} |
|
700 |
};
|
|
700 | 701 |
|
701 | 702 |
// fix for gecko engine |
702 |
Element.cleanWhitespace(element);
|
|
703 |
Element.cleanWhitespace(element); |
|
703 | 704 |
|
704 | 705 |
options.draggables = []; |
705 | 706 |
options.droppables = []; |
... | ... | |
712 | 713 |
|
713 | 714 |
(options.elements || this.findElements(element, options) || []).each( function(e,i) { |
714 | 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 | 717 |
options.draggables.push( |
717 | 718 |
new Draggable(e, Object.extend(options_for_draggable, { handle: handle }))); |
718 | 719 |
Droppables.add(e, options_for_droppable); |
719 | 720 |
if(options.tree) e.treeNode = element; |
720 |
options.droppables.push(e);
|
|
721 |
options.droppables.push(e); |
|
721 | 722 |
}); |
722 |
|
|
723 |
|
|
723 | 724 |
if(options.tree) { |
724 | 725 |
(Sortable.findTreeElements(element, options) || []).each( function(e) { |
725 | 726 |
Droppables.add(e, options_for_tree); |
... | ... | |
741 | 742 |
return Element.findChildren( |
742 | 743 |
element, options.only, options.tree ? true : false, options.tag); |
743 | 744 |
}, |
744 |
|
|
745 |
|
|
745 | 746 |
findTreeElements: function(element, options) { |
746 | 747 |
return Element.findChildren( |
747 | 748 |
element, options.only, options.tree ? true : false, options.treeTag); |
... | ... | |
758 | 759 |
var oldParentNode = element.parentNode; |
759 | 760 |
element.style.visibility = "hidden"; // fix gecko rendering |
760 | 761 |
dropon.parentNode.insertBefore(element, dropon); |
761 |
if(dropon.parentNode!=oldParentNode)
|
|
762 |
if(dropon.parentNode!=oldParentNode) |
|
762 | 763 |
Sortable.options(oldParentNode).onChange(element); |
763 | 764 |
Sortable.options(dropon.parentNode).onChange(element); |
764 | 765 |
} |
... | ... | |
769 | 770 |
var oldParentNode = element.parentNode; |
770 | 771 |
element.style.visibility = "hidden"; // fix gecko rendering |
771 | 772 |
dropon.parentNode.insertBefore(element, nextElement); |
772 |
if(dropon.parentNode!=oldParentNode)
|
|
773 |
if(dropon.parentNode!=oldParentNode) |
|
773 | 774 |
Sortable.options(oldParentNode).onChange(element); |
774 | 775 |
Sortable.options(dropon.parentNode).onChange(element); |
775 | 776 |
} |
776 | 777 |
} |
777 | 778 |
}, |
778 |
|
|
779 |
|
|
779 | 780 |
onEmptyHover: function(element, dropon, overlap) { |
780 | 781 |
var oldParentNode = element.parentNode; |
781 | 782 |
var droponOptions = Sortable.options(dropon); |
782 |
|
|
783 |
|
|
783 | 784 |
if(!Element.isParent(dropon, element)) { |
784 | 785 |
var index; |
785 |
|
|
786 |
|
|
786 | 787 |
var children = Sortable.findElements(dropon, {tag: droponOptions.tag, only: droponOptions.only}); |
787 | 788 |
var child = null; |
788 |
|
|
789 |
|
|
789 | 790 |
if(children) { |
790 | 791 |
var offset = Element.offsetSize(dropon, droponOptions.overlap) * (1.0 - overlap); |
791 |
|
|
792 |
|
|
792 | 793 |
for (index = 0; index < children.length; index += 1) { |
793 | 794 |
if (offset - Element.offsetSize (children[index], droponOptions.overlap) >= 0) { |
794 | 795 |
offset -= Element.offsetSize (children[index], droponOptions.overlap); |
... | ... | |
801 | 802 |
} |
802 | 803 |
} |
803 | 804 |
} |
804 |
|
|
805 |
|
|
805 | 806 |
dropon.insertBefore(element, child); |
806 |
|
|
807 |
|
|
807 | 808 |
Sortable.options(oldParentNode).onChange(element); |
808 | 809 |
droponOptions.onChange(element); |
809 | 810 |
} |
... | ... | |
816 | 817 |
mark: function(dropon, position) { |
817 | 818 |
// mark on ghosting only |
818 | 819 |
var sortable = Sortable.options(dropon.parentNode); |
819 |
if(sortable && !sortable.ghosting) return;
|
|
820 |
if(sortable && !sortable.ghosting) return; |
|
820 | 821 |
|
821 | 822 |
if(!Sortable._marker) { |
822 |
Sortable._marker =
|
|
823 |
Sortable._marker = |
|
823 | 824 |
($('dropmarker') || Element.extend(document.createElement('DIV'))). |
824 | 825 |
hide().addClassName('dropmarker').setStyle({position:'absolute'}); |
825 | 826 |
document.getElementsByTagName("body").item(0).appendChild(Sortable._marker); |
826 |
}
|
|
827 |
} |
|
827 | 828 |
var offsets = Position.cumulativeOffset(dropon); |
828 | 829 |
Sortable._marker.setStyle({left: offsets[0]+'px', top: offsets[1] + 'px'}); |
829 |
|
|
830 |
|
|
830 | 831 |
if(position=='after') |
831 |
if(sortable.overlap == 'horizontal')
|
|
832 |
if(sortable.overlap == 'horizontal') |
|
832 | 833 |
Sortable._marker.setStyle({left: (offsets[0]+dropon.clientWidth) + 'px'}); |
833 | 834 |
else |
834 | 835 |
Sortable._marker.setStyle({top: (offsets[1]+dropon.clientHeight) + 'px'}); |
835 |
|
|
836 |
|
|
836 | 837 |
Sortable._marker.show(); |
837 | 838 |
}, |
838 |
|
|
839 |
|
|
839 | 840 |
_tree: function(element, options, parent) { |
840 | 841 |
var children = Sortable.findElements(element, options) || []; |
841 |
|
|
842 |
|
|
842 | 843 |
for (var i = 0; i < children.length; ++i) { |
843 | 844 |
var match = children[i].id.match(options.format); |
844 | 845 |
|
845 | 846 |
if (!match) continue; |
846 |
|
|
847 |
|
|
847 | 848 |
var child = { |
848 | 849 |
id: encodeURIComponent(match ? match[1] : null), |
849 | 850 |
element: element, |
... | ... | |
851 | 852 |
children: [], |
852 | 853 |
position: parent.children.length, |
853 | 854 |
container: $(children[i]).down(options.treeTag) |
854 |
} |
|
855 |
|
|
855 |
};
|
|
856 |
|
|
856 | 857 |
/* Get the element containing the children and recurse over it */ |
857 | 858 |
if (child.container) |
858 |
this._tree(child.container, options, child) |
|
859 |
|
|
859 |
this._tree(child.container, options, child);
|
|
860 |
|
|
860 | 861 |
parent.children.push (child); |
861 | 862 |
} |
862 | 863 |
|
863 |
return parent;
|
|
864 |
return parent; |
|
864 | 865 |
}, |
865 | 866 |
|
866 | 867 |
tree: function(element) { |
... | ... | |
873 | 874 |
name: element.id, |
874 | 875 |
format: sortableOptions.format |
875 | 876 |
}, arguments[1] || { }); |
876 |
|
|
877 |
|
|
877 | 878 |
var root = { |
878 | 879 |
id: null, |
879 | 880 |
parent: null, |
880 | 881 |
children: [], |
881 | 882 |
container: element, |
882 | 883 |
position: 0 |
883 |
} |
|
884 |
|
|
884 |
};
|
|
885 |
|
|
885 | 886 |
return Sortable._tree(element, options, root); |
886 | 887 |
}, |
887 | 888 |
|
... | ... | |
897 | 898 |
sequence: function(element) { |
898 | 899 |
element = $(element); |
899 | 900 |
var options = Object.extend(this.options(element), arguments[1] || { }); |
900 |
|
|
901 |
|
|
901 | 902 |
return $(this.findElements(element, options) || []).map( function(item) { |
902 | 903 |
return item.id.match(options.format) ? item.id.match(options.format)[1] : ''; |
903 | 904 |
}); |
... | ... | |
906 | 907 |
setSequence: function(element, new_sequence) { |
907 | 908 |
element = $(element); |
908 | 909 |
var options = Object.extend(this.options(element), arguments[2] || { }); |
909 |
|
|
910 |
|
|
910 | 911 |
var nodeMap = { }; |
911 | 912 |
this.findElements(element, options).each( function(n) { |
912 | 913 |
if (n.id.match(options.format)) |
913 | 914 |
nodeMap[n.id.match(options.format)[1]] = [n, n.parentNode]; |
914 | 915 |
n.parentNode.removeChild(n); |
915 | 916 |
}); |
916 |
|
|
917 |
|
|
917 | 918 |
new_sequence.each(function(ident) { |
918 | 919 |
var n = nodeMap[ident]; |
919 | 920 |
if (n) { |
... | ... | |
922 | 923 |
} |
923 | 924 |
}); |
924 | 925 |
}, |
925 |
|
|
926 |
|
|
926 | 927 |
serialize: function(element) { |
927 | 928 |
element = $(element); |
928 | 929 |
var options = Object.extend(Sortable.options(element), arguments[1] || { }); |
929 | 930 |
var name = encodeURIComponent( |
930 | 931 |
(arguments[1] && arguments[1].name) ? arguments[1].name : element.id); |
931 |
|
|
932 |
|
|
932 | 933 |
if (options.tree) { |
933 | 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 | 936 |
encodeURIComponent(item.id)].concat(item.children.map(arguments.callee)); |
936 | 937 |
}).flatten().join('&'); |
937 | 938 |
} else { |
... | ... | |
940 | 941 |
}).join('&'); |
941 | 942 |
} |
942 | 943 |
} |
943 |
} |
|
944 |
};
|
|
944 | 945 |
|
945 | 946 |
// Returns true if child is contained within element |
946 | 947 |
Element.isParent = function(child, element) { |
947 | 948 |
if (!child.parentNode || child == element) return false; |
948 | 949 |
if (child.parentNode == element) return true; |
949 | 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 | 954 |
if(!element.hasChildNodes()) return null; |
954 | 955 |
tagName = tagName.toUpperCase(); |
955 | 956 |
if(only) only = [only].flatten(); |
... | ... | |
965 | 966 |
}); |
966 | 967 |
|
967 | 968 |
return (elements.length>0 ? elements.flatten() : []); |
968 |
} |
|
969 |
};
|
|
969 | 970 |
|
970 | 971 |
Element.offsetSize = function (element, type) { |
971 | 972 |
return element['offset' + ((type=='vertical' || type=='height') ? 'Height' : 'Width')]; |
972 |
} |
|
973 |
};
|
sandbox/rails-2.2/public/javascripts/effects.js | ||
---|---|---|
3 | 3 |
// Justin Palmer (http://encytemedia.com/) |
4 | 4 |
// Mark Pilgrim (http://diveintomark.org/) |
5 | 5 |
// Martin Bialasinki |
6 |
//
|
|
6 |
// |
|
7 | 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,
|
|
11 |
// returns self (or first argument) if not convertable
|
|
12 |
String.prototype.parseColor = function() {
|
|
10 |
// converts rgb() and #xxx to #xxxxxx format, |
|
11 |
// returns self (or first argument) if not convertable |
|
12 |
String.prototype.parseColor = function() { |
|
13 | 13 |
var color = '#'; |
14 |
if (this.slice(0,4) == 'rgb(') {
|
|
15 |
var cols = this.slice(4,this.length-1).split(',');
|
|
16 |
var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3);
|
|
17 |
} else {
|
|
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();
|
|
20 |
if (this.length==7) color = this.toLowerCase();
|
|
21 |
}
|
|
22 |
}
|
|
23 |
return (color.length==7 ? color : (arguments[0] || this));
|
|
14 |
if (this.slice(0,4) == 'rgb(') { |
|
15 |
var cols = this.slice(4,this.length-1).split(','); |
|
16 |
var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3); |
|
17 |
} else { |
|
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(); |
|
20 |
if (this.length==7) color = this.toLowerCase(); |
|
21 |
} |
|
22 |
} |
|
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 | 29 |
return $A($(element).childNodes).collect( function(node) { |
30 |
return (node.nodeType==3 ? node.nodeValue :
|
|
30 |
return (node.nodeType==3 ? node.nodeValue : |
|
31 | 31 |
(node.hasChildNodes() ? Element.collectTextNodes(node) : '')); |
32 | 32 |
}).flatten().join(''); |
33 | 33 |
}; |
34 | 34 |
|
35 |
Element.collectTextNodesIgnoreClass = function(element, className) {
|
|
35 |
Element.collectTextNodesIgnoreClass = function(element, className) { |
|
36 | 36 |
return $A($(element).childNodes).collect( function(node) { |
37 |
return (node.nodeType==3 ? node.nodeValue :
|
|
38 |
((node.hasChildNodes() && !Element.hasClassName(node,className)) ?
|
|
37 |
return (node.nodeType==3 ? node.nodeValue : |
|
38 |
((node.hasChildNodes() && !Element.hasClassName(node,className)) ? |
|
39 | 39 |
Element.collectTextNodesIgnoreClass(node, className) : '')); |
40 | 40 |
}).flatten().join(''); |
41 | 41 |
}; |
42 | 42 |
|
43 | 43 |
Element.setContentZoom = function(element, percent) { |
44 |
element = $(element);
|
|
45 |
element.setStyle({fontSize: (percent/100) + 'em'});
|
|
44 |
element = $(element); |
|
45 |
element.setStyle({fontSize: (percent/100) + 'em'}); |
|
46 | 46 |
if (Prototype.Browser.WebKit) window.scrollBy(0,0); |
47 | 47 |
return element; |
48 | 48 |
}; |
... | ... | |
70 | 70 |
Transitions: { |
71 | 71 |
linear: Prototype.K, |
72 | 72 |
sinoidal: function(pos) { |
73 |
return (-Math.cos(pos*Math.PI)/2) + 0.5;
|
|
73 |
return (-Math.cos(pos*Math.PI)/2) + .5; |
|
74 | 74 |
}, |
75 | 75 |
reverse: function(pos) { |
76 | 76 |
return 1-pos; |
77 | 77 |
}, |
78 | 78 |
flicker: function(pos) { |
79 |
var pos = ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4;
|
|
79 |
var pos = ((-Math.cos(pos*Math.PI)/4) + .75) + Math.random()/4; |
|
80 | 80 |
return pos > 1 ? 1 : pos; |
81 | 81 |
}, |
82 | 82 |
wobble: function(pos) { |
83 |
return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5;
|
|
83 |
return (-Math.cos(pos*Math.PI*(9*pos))/2) + .5; |
|
84 | 84 |
}, |
85 |
pulse: function(pos, pulses) { |
Also available in: Unified diff
rake rails:update