diff options
Diffstat (limited to 'actionpack/lib/action_view')
-rw-r--r-- | actionpack/lib/action_view/helpers/javascripts/dragdrop.js | 122 | ||||
-rw-r--r-- | actionpack/lib/action_view/helpers/javascripts/effects.js | 86 |
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, |