Created
June 5, 2010 09:01
-
-
Save miya2000/426464 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| if (window.top != window.self) { | |
| // たぶん BackCompat じゃないと動かない。 | |
| if (this.scrollable.isRoot()) { | |
| document.body.style.height = '100%'; | |
| document.body.style.overflow = 'hidden'; | |
| } | |
| detach.push(subscribe(window, 'focus', bind(this, function() { | |
| var left = -parseInt(document.documentElement.style.marginLeft, 10) || 0; | |
| var top = -parseInt(document.documentElement.style.marginTop, 10) || 0; | |
| document.documentElement.style.marginLeft = ''; | |
| document.documentElement.style.marginTop = ''; | |
| document.body.style.height = ''; | |
| document.body.style.overflow = ''; | |
| this.scrollable.scrollTo(left, top); | |
| }))); | |
| detach.push(subscribe(window, 'blur', bind(this, function() { | |
| var left = this.scrollable.getScrollLeft(); | |
| var top = this.scrollable.getScrollTop(); | |
| document.body.style.height = '100%'; | |
| document.body.style.overflow = 'hidden'; | |
| document.documentElement.style.marginLeft = -left + 'px'; | |
| document.documentElement.style.marginTop = -top + 'px'; | |
| }))); | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| var Browser = { | |
| Opera: !!window.opera, | |
| Opera_version: window.opera ? parseFloat(window.opera.version()) : null, | |
| Webkit: (navigator.userAgent.indexOf(' AppleWebKit/') >= 0) | |
| }; | |
| /// class Scrollable - scrollable element wrapper. | |
| function Scrollable(element) { | |
| if (!(this instanceof Scrollable)) return new Scrollable(element); | |
| this.element = element; | |
| this.scrollElement = element; | |
| if (this.isRoot() && Browser.Webkit) { | |
| this.scrollElement = document.body; | |
| } | |
| this.scroller = { | |
| '1': new Smooth(this.scrollElement, 'scrollLeft'), | |
| '2': new Smooth(this.scrollElement, 'scrollTop') | |
| }; | |
| this.scroller[1].easing = this.scroller[2].easing = Smooth.easings.easeOutSine; | |
| this.scroller[1].duration = this.scroller[2].duration = function(change, sliding) { | |
| var abs = (change ^ (change >> 31)) - (change >> 31); // Math.abs(change); | |
| if (abs < 120) return this.baseDuration * (abs / 120) | 0; | |
| return this.baseDuration; | |
| }; | |
| if (this.isRoot() && Browser.Webkit) { | |
| this.scroller[1].onprogress = this.scroller[2].onprogress = function() { | |
| Scrollable.fn.dispatchScrollEvent(document); | |
| }; | |
| } | |
| } | |
| Scrollable.HORIZONTAL_AXIS = 1; // compatible MouseScrollEvent(Gecko). | |
| Scrollable.VERTICAL_AXIS = 2; | |
| var Sfn = Scrollable.fn = (function() { | |
| //[[navico notation]] | |
| return { | |
| getRoot: getRoot, | |
| isRoot: isRoot, | |
| dispatchScrollEvent: dispatchScrollEvent, | |
| getClientWidth: getClientWidth, | |
| getClientHeight: getClientHeight, | |
| getScrollWidth: getScrollWidth, | |
| getScrollHeight: getScrollHeight, | |
| getScrollLeft: getScrollLeft, | |
| getScrollTop: getScrollTop, | |
| getScrollElement: getScrollElement, | |
| isScrollable: isScrollable, | |
| isScrollableNode: isScrollableNode, | |
| scrollDirectTo: scrollDirectTo, | |
| scrollDirectBy: scrollDirectBy, | |
| scrollTo: scrollTo, | |
| scrollBy: scrollBy | |
| }; | |
| function getRoot() { | |
| return Scrollable.ROOT || (Scrollable.ROOT = (document.compatMode == 'BackCompat') ? document.body : document.documentElement); | |
| } | |
| function isRoot(ele) { | |
| return ele === getRoot(); | |
| } | |
| function dispatchScrollEvent(target) { | |
| var ev = document.createEvent('HTMLEvents'); | |
| ev.initEvent('scroll', true, false); | |
| target.dispatchEvent(ev); | |
| } | |
| function getClientWidth(viewElement) { | |
| return viewElement.clientWidth; | |
| } | |
| function getClientHeight(viewElement) { | |
| return viewElement.clientHeight; | |
| } | |
| function getScrollWidth(scrollElement) { | |
| if (Browser.Opera) { | |
| var style = document.defaultView.getComputedStyle(scrollElement, ''); | |
| var pad = 0; | |
| if (Browser.Opera_version <= 10.10) { | |
| pad -= parseInt(style.borderLeftWidth, 10); | |
| } | |
| else { | |
| pad += parseInt(style.paddingLeft, 10); | |
| } | |
| return scrollElement.scrollWidth + pad; | |
| } | |
| else { | |
| return scrollElement.scrollWidth; | |
| } | |
| } | |
| function getScrollHeight(scrollElement) { | |
| if (Browser.Opera && !isRoot(scrollElement)) { | |
| var style = document.defaultView.getComputedStyle(scrollElement, ''); | |
| var pad = 0; | |
| pad += parseInt(style.paddingTop, 10); | |
| return scrollElement.scrollHeight + pad; | |
| } | |
| else { | |
| return scrollElement.scrollHeight; | |
| } | |
| } | |
| function getScrollLeft(scrollElement) { | |
| return scrollElement.scrollLeft; | |
| } | |
| function getScrollTop(scrollElement) { | |
| return scrollElement.scrollTop; | |
| } | |
| function getScrollElement(ele) { | |
| if (isRoot(ele) && Browser.Webkit) return document.body; | |
| return ele; | |
| } | |
| function isScrollable(ele, h1v2orBoth, u1d2orBoth) { | |
| var scr = getScrollElement(ele); | |
| if (h1v2orBoth == 1) { | |
| if (u1d2orBoth == 1) return getScrollLeft(scr) > 0; | |
| if (u1d2orBoth == 2) return getScrollLeft(scr) < getScrollWidth(scr) - getClientWidth(ele); | |
| return getScrollWidth(scr) > getClientWidth(ele); | |
| } | |
| if (h1v2orBoth == 2) { | |
| if (u1d2orBoth == 1) return getScrollTop(scr) > 0; | |
| if (u1d2orBoth == 2) return getScrollTop(scr) < getScrollHeight(scr) - getClientHeight(ele); | |
| return getScrollHeight(scr) > getClientHeight(ele); | |
| } | |
| return (getScrollWidth(scr) > getClientWidth(ele)) && (getScrollHeight(scr) > getClientHeight(ele)); | |
| } | |
| function isScrollableNode(ele, h1v2) { | |
| if (!ele || ele.nodeType != 1) return false; | |
| if (isRoot(ele)) return true; | |
| if (ele.nodeName == 'TEXTAREA') return true; | |
| var style = document.defaultView.getComputedStyle(ele, ''); | |
| if (style.display != 'block') return false; | |
| if (typeof style.overflowY == 'undefined') { | |
| return /^(auto|scroll)$/.test(style.overflow); | |
| } | |
| else { | |
| if (h1v2 == 1) return /^(auto|scroll)$/.test(style.overflowX); | |
| if (h1v2 == 2) return /^(auto|scroll)$/.test(style.overflowY); | |
| return /^(auto|scroll)$/.test(style.overflow); | |
| } | |
| } | |
| function scrollDirectTo(ele, h1v2, to) { | |
| var dest = to, max, scr = getScrollElement(ele); | |
| if (h1v2 == 1) max = getScrollWidth(scr) - getClientWidth(ele); | |
| if (h1v2 == 2) max = getScrollHeight(scr) - getClientHeight(ele); | |
| if (dest < 0 ) dest = 0; | |
| if (dest > max) dest = max; | |
| if (h1v2 == 1) scr.scrollLeft = dest; | |
| if (h1v2 == 2) scr.scrollTop = dest; | |
| if (isRoot(ele) && Browser.Webkit) { | |
| dispatchScrollEvent(document); | |
| } | |
| } | |
| function scrollDirectBy(ele, h1v2, delta) { | |
| Sfn.scrollDirectTo(ele, h1v2, (h1v2 == 1 ? getScrollLeft(ele) : getScrollTop(ele)) + delta); | |
| } | |
| function scrollTo(ele, x, y) { | |
| if (x != null) Sfn.scrollDirectTo(ele, 1, x); | |
| if (y != null) Sfn.scrollDirectTo(ele, 2, y); | |
| } | |
| function scrollBy(ele, dx, dy) { | |
| if (dx != null) Sfn.scrollDirectBy(ele, 1, dx); | |
| if (dy != null) Sfn.scrollDirectBy(ele, 2, dy); | |
| } | |
| })(); | |
| (function(member) { member.apply(Scrollable.prototype); })(function() { | |
| this.isRoot = function() { return Sfn.isRoot(this.element); }; | |
| this.getClientWidth = function() { return Sfn.getClientWidth(this.element); }; | |
| this.getClientHeight = function() { return Sfn.getClientHeight(this.element); }; | |
| this.getScrollWidth = function() { return Sfn.getScrollWidth(this.scrollElement); }; | |
| this.getScrollHeight = function() { return Sfn.getScrollHeight(this.scrollElement); }; | |
| this.getScrollLeft = function() { return Sfn.getScrollLeft(this.scrollElement); }; | |
| this.getScrollTop = function() { return Sfn.getScrollTop(this.scrollElement); }; | |
| this.isScrollable = function(h1v2, u1d2) { return Sfn.isScrollable(this.element, h1v2, u1d2); }; | |
| this.isScrollableNode = function() { return Sfn.isScrollableNode(this.element); }; | |
| this.scrollDirectTo = function scrollDirectTo(h1v2, to, smooth) { | |
| if (!smooth) { | |
| Sfn.scrollDirectTo(this.element, h1v2, to); | |
| return; | |
| } | |
| var dest = to, max; | |
| if (h1v2 == 1) max = this.getScrollWidth() - this.getClientWidth(); | |
| if (h1v2 == 2) max = this.getScrollHeight() - this.getClientHeight(); | |
| if (dest < 0 ) dest = 0; | |
| if (dest > max) dest = max; | |
| this.scroller[h1v2].go(dest); | |
| }; | |
| this.scrollDirectBy = function scrollDirectBy(h1v2, delta, smooth) { | |
| var scroller = this.scroller[h1v2]; | |
| var from = scroller.isActive ? scroller.dest : scroller.current(); | |
| this.scrollDirectTo(h1v2, from + delta, smooth); | |
| }; | |
| this.scrollTo = function scrollTo(x, y, smooth) { | |
| if (x != null) this.scrollDirectTo(1, x, smooth); | |
| if (y != null) this.scrollDirectTo(2, y, smooth); | |
| }; | |
| this.scrollBy = function scrollTo(dx, dy, smooth) { | |
| if (dx != null) this.scrollDirectBy(1, dx, smooth); | |
| if (dy != null) this.scrollDirectBy(2, dy, smooth); | |
| }; | |
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /// class Smooth - simple smooth animation. | |
| function Smooth(target, property, baseDuration, delay, initialRatio) { | |
| this.target = target; | |
| this.property = property; | |
| this.baseDuration = baseDuration || 180; | |
| this.delay = delay || 16; | |
| this.initialRatio = initialRatio || 0; | |
| } | |
| Smooth.easings = { | |
| easeNone : function easeNone(t, b, c, d) { return c*t/d + b; }, | |
| easeInSine : function easeInSine(t, b, c, d) { return -c * Math.cos(t/d *(Math.PI/2)) + c + b; }, | |
| easeOutSine : function easeOutSine(t, b, c, d) { return c * Math.sin(t/d *(Math.PI/2)) + b; }, | |
| easeInExpo : function easeInExpo(t, b, c, d) { return(t==0) ? b : c * Math.pow(2, 10 *(t/d - 1)) + b - c * 0.001; }, | |
| easeOutExpo : function easeOutExpo(t, b, c, d) { return(t==d) ? b+c : c * 1.001 *(-Math.pow(2, -10 * t/d) + 1) + b; } | |
| }; | |
| (function(member) { member.apply(Smooth.prototype) })(function() { | |
| this.easing = Smooth.easings.easeOutExpo; | |
| this.duration = function(change, sliding) { return this.baseDuration; }; | |
| this.go = function(/*from, */dest) { | |
| var target = this.target, prop = this.property, from; | |
| if (arguments.length > 1) { | |
| from = arguments[0]; | |
| dest = arguments[1]; | |
| } | |
| else { | |
| from = target[prop]; | |
| } | |
| if (this.isActive) { | |
| if (this.dest == dest) return; | |
| this.dest = dest; | |
| this.activity.slide(dest); | |
| return; | |
| } | |
| var begin = parseFloat(from) || 0, end = parseFloat(dest), change = end - begin; | |
| if (this.initialRatio) begin += change * this.initialRatio; | |
| var m = /[0-9]*\.?([0-9]*)(.*)/.exec(dest), scale = (m ? m[1].length : 0), unit = (m ? m[2] : null); | |
| var power = Math.pow(10, scale); | |
| var start = new Date(), duration = this.duration(change, false); | |
| this.from = from; this.dest = dest; this.isActive = true; | |
| this.activity = { | |
| slide: slide, | |
| anim: anim, | |
| dispose: dispose | |
| }; | |
| var self = this; | |
| function slide(dest) { | |
| var cur = parseFloat(self.current()); | |
| if (!isNaN(cur)) begin = cur; | |
| end = parseFloat(dest); | |
| change = end - begin; | |
| start = new Date(); | |
| duration = self.duration(change, true); | |
| } | |
| function anim() { | |
| var finished = false; | |
| try { | |
| var time = new Date() - start, next; | |
| if (time >= duration) { | |
| next = self.dest; | |
| finished = true; | |
| } | |
| else { | |
| next = (self.easing(time, begin, change, duration) * power + 0.5 | 0) / power; // not strict round at negative value. | |
| if (unit) next = next + unit; | |
| if (next == self.dest) finished = true; | |
| } | |
| target[prop] = next; | |
| } | |
| catch(e) { self.clear(); throw e; } | |
| if (finished) { | |
| self.clear(); | |
| if (self.onfinish) self.onfinish(); | |
| } | |
| else { | |
| if (self.onprogress) self.onprogress(); | |
| } | |
| } | |
| var tid = setInterval(anim, this.delay); | |
| function dispose() { if (tid) clearInterval(tid); tid = null; } | |
| if (arguments.length > 1 || duration <= 0) anim(); // call first if "from" set or "duration" isn't set. | |
| }; | |
| this.current = function() { | |
| return this.target[this.property]; | |
| }; | |
| this.clear = function() { | |
| this.isActive = false; | |
| if (this.activity != null) this.activity.dispose(); | |
| this.activity = null; | |
| }; | |
| this.restore = function() { | |
| if (this.from != null) this.target[this.property] = this.from; | |
| this.clear(); | |
| }; | |
| }); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment