aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack/lib')
-rw-r--r--actionpack/lib/action_view/helpers/javascripts/dragdrop.js122
-rw-r--r--actionpack/lib/action_view/helpers/javascripts/effects.js86
2 files changed, 133 insertions, 75 deletions
diff --git a/actionpack/lib/action_view/helpers/javascripts/dragdrop.js b/actionpack/lib/action_view/helpers/javascripts/dragdrop.js
index eb6511095f..2bf84f1cb1 100644
--- a/actionpack/lib/action_view/helpers/javascripts/dragdrop.js
+++ b/actionpack/lib/action_view/helpers/javascripts/dragdrop.js
@@ -112,6 +112,12 @@ Element.Class = {
var Droppables = {
drops: false,
+ remove: function(element) {
+ for(var i = 0; i < this.drops.length; i++)
+ if(this.drops[i].element == element)
+ this.drops.splice(i,1);
+ },
+
add: function(element) {
var element = $(element);
var options = {
@@ -134,43 +140,42 @@ var Droppables = {
options._containers.length-1;
}
- if(element.style.position=='') //fix IE
- element.style.position = 'relative';
+ Element.makePositioned(element); // fix IE
- // activate the droppable
- element.droppable = options;
+ options.element = element;
+ // activate the droppable
if(!this.drops) this.drops = [];
- this.drops.push(element);
+ this.drops.push(options);
},
is_contained: function(element, drop) {
- var containers = drop.droppable._containers;
+ var containers = drop._containers;
var parentNode = element.parentNode;
- var i = drop.droppable._containers_length;
+ var i = drop._containers_length;
do { if(parentNode==containers[i]) return true; } while (i--);
return false;
},
is_affected: function(pX, pY, element, drop) {
return (
- (drop!=element) &&
- ((!drop.droppable._containers) ||
+ (drop.element!=element) &&
+ ((!drop._containers) ||
this.is_contained(element, drop)) &&
- ((!drop.droppable.accept) ||
- (Element.Class.has_any(element, drop.droppable.accept))) &&
- Position.within(drop, pX, pY) );
+ ((!drop.accept) ||
+ (Element.Class.has_any(element, drop.accept))) &&
+ Position.within(drop.element, pX, pY) );
},
deactivate: function(drop) {
- Element.Class.remove(drop, drop.droppable.hoverclass);
+ Element.Class.remove(drop.element, drop.hoverclass);
this.last_active = null;
},
activate: function(drop) {
if(this.last_active) this.deactivate(this.last_active);
- if(drop.droppable.hoverclass) {
- Element.Class.add(drop, drop.droppable.hoverclass);
+ if(drop.hoverclass) {
+ Element.Class.add(drop.element, drop.hoverclass);
this.last_active = drop;
}
},
@@ -184,10 +189,9 @@ var Droppables = {
var i = this.drops.length-1; do {
var drop = this.drops[i];
if(this.is_affected(pX, pY, element, drop)) {
- if(drop.droppable.onHover)
- drop.droppable.onHover(
- element, drop, Position.overlap(drop.droppable.overlap, drop));
- if(drop.droppable.greedy) {
+ if(drop.onHover)
+ drop.onHover(element, drop.element, Position.overlap(drop.overlap, drop.element));
+ if(drop.greedy) {
this.activate(drop);
return;
}
@@ -200,8 +204,8 @@ var Droppables = {
Position.prepare();
if (this.is_affected(Event.pointerX(event), Event.pointerY(event), element, this.last_active))
- if (this.last_active.droppable.onDrop)
- this.last_active.droppable.onDrop(element, this.last_active);
+ if (this.last_active.onDrop)
+ this.last_active.onDrop(element, this.last_active);
},
@@ -216,6 +220,11 @@ Draggables = {
addObserver: function(observer) {
this.observers.push(observer);
},
+ removeObserver: function(observer) {
+ for(var i = 0; i < this.observers.length; i++)
+ if(this.observers[i] = observer)
+ this.observers.splice(i,1);
+ },
notify: function(eventName, draggable) { // 'onStart', 'onEnd'
for(var i = 0; i < this.observers.length; i++)
this.observers[i][eventName](draggable);
@@ -245,9 +254,7 @@ Draggable.prototype = {
this.element = $(element);
this.handle = options.handle ? $(options.handle) : this.element;
- // fix IE
- if(!this.element.style.position)
- this.element.style.position = 'relative';
+ Element.makePositioned(this.element); // fix IE
this.offsetX = 0;
this.offsetY = 0;
@@ -262,10 +269,21 @@ Draggable.prototype = {
this.active = false;
this.dragging = false;
- Event.observe(this.handle, "mousedown", this.startDrag.bindAsEventListener(this));
- Event.observe(document, "mouseup", this.endDrag.bindAsEventListener(this));
- Event.observe(document, "mousemove", this.update.bindAsEventListener(this));
- Event.observe(document, "keypress", this.keyPress.bindAsEventListener(this));
+ this.eventMouseDown = this.startDrag.bindAsEventListener(this);
+ this.eventMouseUp = this.endDrag.bindAsEventListener(this);
+ this.eventMouseMove = this.update.bindAsEventListener(this);
+ this.eventKeypress = this.keyPress.bindAsEventListener(this);
+
+ Event.observe(this.handle, "mousedown", this.eventMouseDown);
+ Event.observe(document, "mouseup", this.eventMouseUp);
+ Event.observe(document, "mousemove", this.eventMouseMove);
+ Event.observe(document, "keypress", this.eventKeypress);
+ },
+ destroy: function() {
+ Event.stopObserving(this.handle, "mousedown", this.eventMouseDown);
+ Event.stopObserving(document, "mouseup", this.eventMouseUp);
+ Event.stopObserving(document, "mousemove", this.eventMouseMove);
+ Event.stopObserving(document, "keypress", this.eventKeypress);
},
currentLeft: function() {
return parseInt(this.element.style.left || '0');
@@ -380,9 +398,32 @@ SortableObserver.prototype = {
}
Sortable = {
+ sortables: new Array(),
+ options: function(element){
+ var element = $(element);
+ for(var i=0;i<this.sortables.length;i++)
+ if(this.sortables[i].element == element)
+ return this.sortables[i];
+ return null;
+ },
+ destroy: function(element){
+ var element = $(element);
+ for(var i=0;i<this.sortables.length;i++) {
+ if(this.sortables[i].element == element) {
+ var s = this.sortables[i];
+ Draggables.removeObserver(s.observer);
+ for(var j=0;j<s.droppables.length;j++)
+ Droppables.remove(s.droppables[j]);
+ for(var j=0;j<s.draggables.length;j++)
+ s.draggables[j].destroy();
+ this.sortables.splice(i,1);
+ }
+ }
+ },
create: function(element) {
var element = $(element);
var options = {
+ element: element,
tag: 'li', // assumes li children, override with tag: 'tagname'
overlap: 'vertical', // one of 'vertical', 'horizontal'
constraint: 'vertical', // one of 'vertical', 'horizontal', false
@@ -393,7 +434,9 @@ Sortable = {
onChange: function() {},
onUpdate: function() {}
}.extend(arguments[1] || {});
- element.sortable = options;
+
+ // clear any old sortable with same element
+ this.destroy(element);
// build options for the draggables
var options_for_draggable = {
@@ -443,8 +486,8 @@ Sortable = {
// fix for gecko engine
Element.cleanWhitespace(element);
- // for onupdate
- Draggables.addObserver(new SortableObserver(element, options.onUpdate));
+ options.draggables = [];
+ options.droppables = [];
// make it so
var elements = element.childNodes;
@@ -456,16 +499,27 @@ Sortable = {
var handle = options.handle ?
Element.Class.childrenWith(elements[i], options.handle)[0] : elements[i];
- new Draggable(elements[i], options_for_draggable.extend({ handle: handle }));
+ options.draggables.push(new Draggable(elements[i], options_for_draggable.extend({ handle: handle })));
+
Droppables.add(elements[i], options_for_droppable);
+ options.droppables.push(elements[i]);
+
}
+ // keep reference
+ this.sortables.push(options);
+
+ // for onupdate
+ options.observer = new SortableObserver(element, options.onUpdate);
+ Draggables.addObserver(options.observer);
+
},
serialize: function(element) {
var element = $(element);
+ var sortableOptions = this.options(element);
var options = {
- tag: element.sortable.tag,
- only: element.sortable.only,
+ tag: sortableOptions.tag,
+ only: sortableOptions.only,
name: element.id
}.extend(arguments[1] || {});
diff --git a/actionpack/lib/action_view/helpers/javascripts/effects.js b/actionpack/lib/action_view/helpers/javascripts/effects.js
index 2b27052cda..abc706673b 100644
--- a/actionpack/lib/action_view/helpers/javascripts/effects.js
+++ b/actionpack/lib/action_view/helpers/javascripts/effects.js
@@ -127,26 +127,26 @@ Effect.Base.prototype = {
}
Effect.Parallel = Class.create();
- Effect.Parallel.prototype = (new Effect.Base()).extend({
- initialize: function(effects) {
- this.effects = effects || [];
- this.start(arguments[1]);
- },
- update: function(position) {
- for (var i = 0; i < this.effects.length; i++)
- this.effects[i].render(position);
- },
- finish: function(position) {
- for (var i = 0; i < this.effects.length; i++)
- if(this.effects[i].finish) this.effects[i].finish(position);
- }
- });
+Effect.Parallel.prototype.extend(Effect.Base.prototype).extend({
+ initialize: function(effects) {
+ this.effects = effects || [];
+ this.start(arguments[1]);
+ },
+ update: function(position) {
+ for (var i = 0; i < this.effects.length; i++)
+ this.effects[i].render(position);
+ },
+ finish: function(position) {
+ for (var i = 0; i < this.effects.length; i++)
+ if(this.effects[i].finish) this.effects[i].finish(position);
+ }
+});
// Internet Explorer caveat: works only on elements the have
// a 'layout', meaning having a given width or height.
// There is no way to safely set this automatically.
Effect.Opacity = Class.create();
-Effect.Opacity.prototype = (new Effect.Base()).extend({
+Effect.Opacity.prototype.extend(Effect.Base.prototype).extend({
initialize: function(element) {
this.element = $(element);
options = {
@@ -166,29 +166,29 @@ Effect.Opacity.prototype = (new Effect.Base()).extend({
});
Effect.MoveBy = Class.create();
- Effect.MoveBy.prototype = (new Effect.Base()).extend({
- initialize: function(element, toTop, toLeft) {
- this.element = $(element);
- this.originalTop = parseFloat(this.element.style.top || '0');
- this.originalLeft = parseFloat(this.element.style.left || '0');
- this.toTop = toTop;
- this.toLeft = toLeft;
- Element.makePositioned(this.element);
- this.start(arguments[3]);
- },
- update: function(position) {
- topd = this.toTop * position + this.originalTop;
- leftd = this.toLeft * position + this.originalLeft;
- this.setPosition(topd, leftd);
- },
- setPosition: function(topd, leftd) {
- this.element.style.top = topd + "px";
- this.element.style.left = leftd + "px";
- }
+Effect.MoveBy.prototype.extend(Effect.Base.prototype).extend({
+ initialize: function(element, toTop, toLeft) {
+ this.element = $(element);
+ this.originalTop = parseFloat(this.element.style.top || '0');
+ this.originalLeft = parseFloat(this.element.style.left || '0');
+ this.toTop = toTop;
+ this.toLeft = toLeft;
+ Element.makePositioned(this.element);
+ this.start(arguments[3]);
+ },
+ update: function(position) {
+ topd = this.toTop * position + this.originalTop;
+ leftd = this.toLeft * position + this.originalLeft;
+ this.setPosition(topd, leftd);
+ },
+ setPosition: function(topd, leftd) {
+ this.element.style.top = topd + "px";
+ this.element.style.left = leftd + "px";
+ }
});
Effect.Scale = Class.create();
-Effect.Scale.prototype = (new Effect.Base()).extend({
+Effect.Scale.prototype.extend(Effect.Base.prototype).extend({
initialize: function(element, percent) {
this.element = $(element)
options = {
@@ -246,7 +246,7 @@ Effect.Scale.prototype = (new Effect.Base()).extend({
});
Effect.Highlight = Class.create();
-Effect.Highlight.prototype = (new Effect.Base()).extend({
+Effect.Highlight.prototype.extend(Effect.Base.prototype).extend({
initialize: function(element) {
this.element = $(element);
@@ -260,8 +260,9 @@ Effect.Highlight.prototype = (new Effect.Base()).extend({
var i=0; do { endcolor += parseInt(cols[i]).toColorPart() } while (++i<3); }
var options = {
- startcolor: "#ffff99",
- endcolor: endcolor
+ startcolor: "#ffff99",
+ endcolor: endcolor,
+ restorecolor: current
}.extend(arguments[1] || {});
// init color calculations
@@ -283,11 +284,14 @@ Effect.Highlight.prototype = (new Effect.Base()).extend({
Math.round(this.colors_base[2]+(this.colors_delta[2]*position)) ];
this.element.style.backgroundColor = "#" +
colors[0].toColorPart() + colors[1].toColorPart() + colors[2].toColorPart();
+ },
+ finish: function() {
+ this.element.style.backgroundColor = this.options.restorecolor;
}
});
Effect.ScrollTo = Class.create();
-Effect.ScrollTo.prototype = (new Effect.Base()).extend({
+Effect.ScrollTo.prototype.extend(Effect.Base.prototype).extend({
initialize: function(element) {
this.element = $(element);
Position.prepare();
@@ -310,7 +314,7 @@ Effect.ScrollTo.prototype = (new Effect.Base()).extend({
/* ------------- prepackaged effects ------------- */
-Effect.Fade = function(element) {
+Effect.Fade = function(element) {
options = {
from: 1.0,
to: 0.0,
@@ -321,7 +325,7 @@ Effect.Fade = function(element) {
new Effect.Opacity(element,options);
}
-Effect.Appear = function(element) {
+Effect.Appear = function(element) {
options = {
from: 0.0,
to: 1.0,