// MooTools: the javascript framework. // Load this file's selection again by visiting: http://mootools.net/more/5fb29d24c3a346e2b8fcf68d206003a4 // Or build this file again with packager using: packager build More/More More/Fx.Scroll More/Drag /* --- script: More.js name: More description: MooTools More license: MIT-style license authors: - Guillermo Rauch - Thomas Aylott - Scott Kyle - Arian Stolwijk - Tim Wienk - Christoph Pojer - Aaron Newton - Jacob Thornton requires: - Core/MooTools provides: [MooTools.More] ... */ MooTools.More = { 'version': '1.3.2.1', 'build': 'e586bcd2496e9b22acfde32e12f84d49ce09e59d' }; /* --- script: Fx.Scroll.js name: Fx.Scroll description: Effect to smoothly scroll any element, including the window. license: MIT-style license authors: - Valerio Proietti requires: - Core/Fx - Core/Element.Event - Core/Element.Dimensions - /MooTools.More provides: [Fx.Scroll] ... */ (function(){ Fx.Scroll = new Class({ Extends: Fx, options: { offset: {x: 0, y: 0}, wheelStops: true }, initialize: function(element, options){ this.element = this.subject = document.id(element); this.parent(options); if (typeOf(this.element) != 'element') this.element = document.id(this.element.getDocument().body); if (this.options.wheelStops){ var stopper = this.element, cancel = this.cancel.pass(false, this); this.addEvent('start', function(){ stopper.addEvent('mousewheel', cancel); }, true); this.addEvent('complete', function(){ stopper.removeEvent('mousewheel', cancel); }, true); } }, set: function(){ var now = Array.flatten(arguments); if (Browser.firefox) now = [Math.round(now[0]), Math.round(now[1])]; // not needed anymore in newer firefox versions this.element.scrollTo(now[0], now[1]); return this; }, compute: function(from, to, delta){ return [0, 1].map(function(i){ return Fx.compute(from[i], to[i], delta); }); }, start: function(x, y){ if (!this.check(x, y)) return this; var scroll = this.element.getScroll(); return this.parent([scroll.x, scroll.y], [x, y]); }, calculateScroll: function(x, y){ var element = this.element, scrollSize = element.getScrollSize(), scroll = element.getScroll(), size = element.getSize(), offset = this.options.offset, values = {x: x, y: y}; for (var z in values){ if (!values[z] && values[z] !== 0) values[z] = scroll[z]; if (typeOf(values[z]) != 'number') values[z] = scrollSize[z] - size[z]; values[z] += offset[z]; } return [values.x, values.y]; }, toTop: function(){ return this.start.apply(this, this.calculateScroll(false, 0)); }, toLeft: function(){ return this.start.apply(this, this.calculateScroll(0, false)); }, toRight: function(){ return this.start.apply(this, this.calculateScroll('right', false)); }, toBottom: function(){ return this.start.apply(this, this.calculateScroll(false, 'bottom')); }, toElement: function(el, axes){ axes = axes ? Array.from(axes) : ['x', 'y']; var scroll = isBody(this.element) ? {x: 0, y: 0} : this.element.getScroll(); var position = Object.map(document.id(el).getPosition(this.element), function(value, axis){ return axes.contains(axis) ? value + scroll[axis] : false; }); return this.start.apply(this, this.calculateScroll(position.x, position.y)); }, toElementEdge: function(el, axes, offset){ axes = axes ? Array.from(axes) : ['x', 'y']; el = document.id(el); var to = {}, position = el.getPosition(this.element), size = el.getSize(), scroll = this.element.getScroll(), containerSize = this.element.getSize(), edge = { x: position.x + size.x, y: position.y + size.y }; ['x', 'y'].each(function(axis){ if (axes.contains(axis)){ if (edge[axis] > scroll[axis] + containerSize[axis]) to[axis] = edge[axis] - containerSize[axis]; if (position[axis] < scroll[axis]) to[axis] = position[axis]; } if (to[axis] == null) to[axis] = scroll[axis]; if (offset && offset[axis]) to[axis] = to[axis] + offset[axis]; }, this); if (to.x != scroll.x || to.y != scroll.y) this.start(to.x, to.y); return this; }, toElementCenter: function(el, axes, offset){ axes = axes ? Array.from(axes) : ['x', 'y']; el = document.id(el); var to = {}, position = el.getPosition(this.element), size = el.getSize(), scroll = this.element.getScroll(), containerSize = this.element.getSize(); ['x', 'y'].each(function(axis){ if (axes.contains(axis)){ to[axis] = position[axis] - (containerSize[axis] - size[axis]) / 2; } if (to[axis] == null) to[axis] = scroll[axis]; if (offset && offset[axis]) to[axis] = to[axis] + offset[axis]; }, this); if (to.x != scroll.x || to.y != scroll.y) this.start(to.x, to.y); return this; } }); function isBody(element){ return (/^(?:body|html)$/i).test(element.tagName); } })(); /* --- script: Drag.js name: Drag description: The base Drag Class. Can be used to drag and resize Elements using mouse events. license: MIT-style license authors: - Valerio Proietti - Tom Occhinno - Jan Kassens requires: - Core/Events - Core/Options - Core/Element.Event - Core/Element.Style - Core/Element.Dimensions - /MooTools.More provides: [Drag] ... */ var Drag = new Class({ Implements: [Events, Options], options: {/* onBeforeStart: function(thisElement){}, onStart: function(thisElement, event){}, onSnap: function(thisElement){}, onDrag: function(thisElement, event){}, onCancel: function(thisElement){}, onComplete: function(thisElement, event){},*/ snap: 6, unit: 'px', grid: false, style: true, limit: false, handle: false, invert: false, preventDefault: false, stopPropagation: false, modifiers: {x: 'left', y: 'top'} }, initialize: function(){ var params = Array.link(arguments, { 'options': Type.isObject, 'element': function(obj){ return obj != null; } }); this.element = document.id(params.element); this.document = this.element.getDocument(); this.setOptions(params.options || {}); var htype = typeOf(this.options.handle); this.handles = ((htype == 'array' || htype == 'collection') ? $$(this.options.handle) : document.id(this.options.handle)) || this.element; this.mouse = {'now': {}, 'pos': {}}; this.value = {'start': {}, 'now': {}}; this.selection = (Browser.ie) ? 'selectstart' : 'mousedown'; if (Browser.ie && !Drag.ondragstartFixed){ document.ondragstart = Function.from(false); Drag.ondragstartFixed = true; } this.bound = { start: this.start.bind(this), check: this.check.bind(this), drag: this.drag.bind(this), stop: this.stop.bind(this), cancel: this.cancel.bind(this), eventStop: Function.from(false) }; this.attach(); }, attach: function(){ this.handles.addEvent('mousedown', this.bound.start); return this; }, detach: function(){ this.handles.removeEvent('mousedown', this.bound.start); return this; }, start: function(event){ var options = this.options; if (event.rightClick) return; if (options.preventDefault) event.preventDefault(); if (options.stopPropagation) event.stopPropagation(); this.mouse.start = event.page; this.fireEvent('beforeStart', this.element); var limit = options.limit; this.limit = {x: [], y: []}; var z, coordinates; for (z in options.modifiers){ if (!options.modifiers[z]) continue; var style = this.element.getStyle(options.modifiers[z]); // Some browsers (IE and Opera) don't always return pixels. if (style && !style.match(/px$/)){ if (!coordinates) coordinates = this.element.getCoordinates(this.element.getOffsetParent()); style = coordinates[options.modifiers[z]]; } if (options.style) this.value.now[z] = (style || 0).toInt(); else this.value.now[z] = this.element[options.modifiers[z]]; if (options.invert) this.value.now[z] *= -1; this.mouse.pos[z] = event.page[z] - this.value.now[z]; if (limit && limit[z]){ var i = 2; while (i--){ var limitZI = limit[z][i]; if (limitZI || limitZI === 0) this.limit[z][i] = (typeof limitZI == 'function') ? limitZI() : limitZI; } } } if (typeOf(this.options.grid) == 'number') this.options.grid = { x: this.options.grid, y: this.options.grid }; var events = { mousemove: this.bound.check, mouseup: this.bound.cancel }; events[this.selection] = this.bound.eventStop; this.document.addEvents(events); }, check: function(event){ if (this.options.preventDefault) event.preventDefault(); var distance = Math.round(Math.sqrt(Math.pow(event.page.x - this.mouse.start.x, 2) + Math.pow(event.page.y - this.mouse.start.y, 2))); if (distance > this.options.snap){ this.cancel(); this.document.addEvents({ mousemove: this.bound.drag, mouseup: this.bound.stop }); this.fireEvent('start', [this.element, event]).fireEvent('snap', this.element); } }, drag: function(event){ var options = this.options; if (options.preventDefault) event.preventDefault(); this.mouse.now = event.page; for (var z in options.modifiers){ if (!options.modifiers[z]) continue; this.value.now[z] = this.mouse.now[z] - this.mouse.pos[z]; if (options.invert) this.value.now[z] *= -1; if (options.limit && this.limit[z]){ if ((this.limit[z][1] || this.limit[z][1] === 0) && (this.value.now[z] > this.limit[z][1])){ this.value.now[z] = this.limit[z][1]; } else if ((this.limit[z][0] || this.limit[z][0] === 0) && (this.value.now[z] < this.limit[z][0])){ this.value.now[z] = this.limit[z][0]; } } if (options.grid[z]) this.value.now[z] -= ((this.value.now[z] - (this.limit[z][0]||0)) % options.grid[z]); if (options.style) this.element.setStyle(options.modifiers[z], this.value.now[z] + options.unit); else this.element[options.modifiers[z]] = this.value.now[z]; } this.fireEvent('drag', [this.element, event]); }, cancel: function(event){ this.document.removeEvents({ mousemove: this.bound.check, mouseup: this.bound.cancel }); if (event){ this.document.removeEvent(this.selection, this.bound.eventStop); this.fireEvent('cancel', this.element); } }, stop: function(event){ var events = { mousemove: this.bound.drag, mouseup: this.bound.stop }; events[this.selection] = this.bound.eventStop; this.document.removeEvents(events); if (event) this.fireEvent('complete', [this.element, event]); } }); Element.implement({ makeResizable: function(options){ var drag = new Drag(this, Object.merge({ modifiers: { x: 'width', y: 'height' } }, options)); this.store('resizer', drag); return drag.addEvent('drag', function(){ this.fireEvent('resize', drag); }.bind(this)); } });