javascript:(function() { document.title = "YuichirouのJavaScriptメモ"; })(); このページをアンテナに追加 RSSフィード

2007年10月2日

Ten.js 10:52 Ten.js - javascript:(function() { document.title = "YuichirouのJavaScriptメモ"; })(); を含むブックマーク はてなブックマーク - Ten.js - javascript:(function() { document.title = "YuichirouのJavaScriptメモ"; })(); Ten.js - javascript:(function() { document.title = "YuichirouのJavaScriptメモ"; })(); のブックマークコメント


/* Ten */
if (typeof(Ten) == 'undefined') {
    Ten = {};
}
Ten.NAME = 'Ten';
Ten.VERSION = 0.16;

/* Ten.Class */
Ten.Class = function(klass, prototype) {
    if (klass && klass.initialize) {
	var c = klass.initialize;
    } else if(klass && klass.base) {
        var c = function() { return klass.base[0].apply(this, arguments) };
    } else {
	var c = function() {};
    }
    c.prototype = prototype || {};
    c.prototype.constructor = c;
    Ten.Class.inherit(c, klass);
    if (klass && klass.base) {
        for (var i = 0;  i < klass.base.length; i++) {
	    var parent = klass.base[i];
            if (i == 0) {
                c.SUPER = parent;
                c.prototype.SUPER = parent.prototype;
            }
            Ten.Class.inherit(c, parent);
            Ten.Class.inherit(c.prototype, parent.prototype);
        }
    }
    return c;
}
Ten.Class.inherit = function(child,parent) {
    for (var prop in parent) {
        if (typeof(child[prop]) != 'undefined' || prop == 'initialize') continue;
        child[prop] = parent[prop];
    }
}

/*
// Basic Ten Classes
*/
/* Ten.Function */
Ten.Function = new Ten.Class({
    bind: function(f,o) {
        return function() {
            f.apply(o, arguments);
        }
    }
});

/* Ten.JSONP */
Ten.JSONP = new Ten.Class({
    initialize: function(uri,obj,method) {
        if (Ten.JSONP.Callbacks.length) {
            setTimeout(function() {new Ten.JSONP(uri,obj,method)}, 500);
            return;
        }
        var del = uri.match(/\?/) ? '&' : '?';
        uri += del + 'callback=Ten.JSONP.callback';
        if (!uri.match(/timestamp=/)) {
            uri += '&' + encodeURI(new Date());
        }
        if (typeof(obj) == 'function' && typeof(method) == 'undefined') {
            obj = {callback: obj};
            method = 'callback';
        }
        if (obj && method) Ten.JSONP.addCallback(obj,method);
        this.script = document.createElement('script');
        this.script.src = uri;
        this.script.type = 'text/javascript';
        document.getElementsByTagName('head')[0].appendChild(this.script);
    },
    addCallback: function(obj,method) {
        Ten.JSONP.Callbacks.push({object: obj, method: method});
    },
    callback: function(args) {
        // alert('callback called');
        var cbs = Ten.JSONP.Callbacks;
        for (var i = 0; i < cbs.length; i++) {
            var cb = cbs[i];
            cb.object[cb.method].call(cb.object, args);
        }
        Ten.JSONP.Callbacks = [];
    },
    MaxBytes: 1800,
    Callbacks: []
});

/* Ten.XHR */
Ten.XHR = new Ten.Class({
    initialize: function(uri,opts,obj,method) {
        if (!uri) return;
        this.request = Ten.XHR.getXMLHttpRequest();
        if (obj && method) this.callback = {object: obj, method: method};
        var xhr = this;
        var prc = this.processReqChange;
        this.request.onreadystatechange = function() {
            prc.apply(xhr, arguments);
        }
        var method = opts.method || 'GET';
        this.request.open(method, uri, true);
        if (method == 'POST') {
            this.request.setRequestHeader('Content-Type',
                                          'application/x-www-form-urlencoded');
        }
        var data = opts.data ? Ten.XHR.makePostData(opts.data) : null;
        this.request.send(data);
    },
    getXMLHttpRequest: function() {
        var xhr;
        var tryThese = [
            function () { return new XMLHttpRequest(); },
            function () { return new ActiveXObject('Msxml2.XMLHTTP'); },
            function () { return new ActiveXObject('Microsoft.XMLHTTP'); },
            function () { return new ActiveXObject('Msxml2.XMLHTTP.4.0'); },
        ];
        for (var i = 0; i < tryThese.length; i++) {
            var func = tryThese[i];
            try {
                xhr = func;
                return func();
            } catch (e) {
                //alert(e);
            }
        }
        return xhr;
    },
    makePostData: function(data) {
        var pairs = [];
        var regexp = /%20/g;
        for (var k in data) {
            var v = data[k].toString();
            var pair = encodeURIComponent(k).replace(regexp,'+') + '=' +
                encodeURIComponent(v).replace(regexp,'+');
            pairs.push(pair);
        }
        return pairs.join('&');
    }
},{
    processReqChange: function() {
        var req = this.request;
        if (req.readyState == 4) {
            if (req.status == 200) {
                var cb = this.callback;
                if (cb) cb.object[cb.method].call(cb.object, req);
            } else {
                // alert("There was a problem retrieving the XML data:\n" +
                //       req.statusText);
            }
        }
    }
});

/* Ten.Observer */
Ten.Observer = new Ten.Class({
    initialize: function(element,event,obj,method) {
        var func = obj;
        if (typeof(method) == 'string') {
            func = obj[method];
        }
        this.element = element;
        this.event = event;
        this.listener = function(event) {
            return func.call(obj, new Ten.Event(event || window.event));
        }
        if (this.element.addEventListener) {
            if (this.event.match(/^on(.+)$/)) {
                this.event = RegExp.$1;
            }
            this.element.addEventListener(this.event, this.listener, false);
        } else if (this.element.attachEvent) {
            this.element.attachEvent(this.event, this.listener);
        }
    }
},{
    stop: function() {
        if (this.element.removeEventListener) {
            this.element.removeEventListener(this.event,this.listener,false);
        } else if (this.element.detachEvent) {
            this.element.detachEvent(this.event,this.listener);
        }
    }
});

/* Ten.Event */
Ten.Event = new Ten.Class({
    initialize: function(e) {
        this.event = e;
        if (e) {
            this.target = e.target || e.srcElement;
            this.shiftKey = e.shiftKey;
            this.ctrlKey = e.ctrlKey;
            this.altKey = e.altKey;
        }
    },
    keyMap: {
        8:"backspace", 9:"tab", 13:"enter", 19:"pause", 27:"escape", 32:"space",
        33:"pageup", 34:"pagedown", 35:"end", 36:"home", 37:"left", 38:"up",
        39:"right", 40:"down", 44:"printscreen", 45:"insert", 46:"delete",
        112:"f1", 113:"f2", 114:"f3", 115:"f4", 116:"f5", 117:"f6", 118:"f7",
        119:"f8", 120:"f9", 121:"f10", 122:"f11", 123:"f12",
        144:"numlock", 145:"scrolllock"
    }
},{
    mousePosition: function() {
        if (!this.event.clientX) return;
        return Ten.Geometry.getMousePosition(this.event);
    },
    isKey: function(name) {
        var ecode = this.event.keyCode;
        if (!ecode) return;
        var ename = Ten.Event.keyMap[ecode];
        if (!ename) return;
        return (ename == name);
    },
    targetIsFormElements: function() {
        if (!this.target) return;
        var T = (this.target.tagName || '').toUpperCase();
        return (T == 'INPUT' || T == 'SELECT' || T == 'OPTION' ||
                T == 'BUTTON' || T == 'TEXTAREA');
    },
    stop: function() {
        var e = this.event;
        if (e.stopPropagation) {
            e.stopPropagation();
            e.preventDefault();
        } else {
            e.cancelBubble = true;
            e.returnValue = false;
        }
    }
});

/* Ten.EventDispatcher */
Ten.EventDispatcher = new Ten.Class({
    initialize: function() {
        this._eventListeners = {};
    }, 
    implementEventDispatcher: function(obj) {
        Ten.Class.inherit(obj, Ten.EventDispatcher.prototype);
        obj._eventListeners = {};
    }
}, {
    hasEventListener: function(type) {
        return (this._eventListeners[type] instanceof Array && this._eventListeners[type].length > 0);
    },
    addEventListener: function(type, listener) {
        if (!this.hasEventListener(type)) {
            this._eventListeners[type] = [];
        }
        var listeners = this._eventListeners[type];
        for (var i = 0;  i < listeners.length; i++) {
            if (listeners[i] == listener) {
                return;
            }
        }
        listeners.push(listener);
    },
    removeEventListener: function(type, listener) {
        if (this.hasEventListener(type)) {
            var listeners = this._eventListeners[type];
            for (var i = 0;  i < listeners.length; i++) {
                if (listeners[i] == listener) {
                    listeners.splice(i, 1);
                    return;
                }
            }
        }
    },
    dispatchEvent: function(type, opt) {
        if (!this.hasEventListener(type)) return false;
        var listeners = this._eventListeners[type];
        for (var i = 0;  i < listeners.length; i++) {
            listeners[i].call(this, opt);
        }
    }
});

/* Ten.DOM */
Ten.DOM = new Ten.Class({
    getElementsByTagAndClassName: function(tagName, className, parent) {
        if (typeof(parent) == 'undefined') parent = document;
        if (!tagName) return Ten.DOM.getElementsByClassName(className, parent);
        var children = parent.getElementsByTagName(tagName);
        if (className) { 
            var elements = [];
            for (var i = 0; i < children.length; i++) {
                var child = children[i];
                if (Ten.DOM.hasClassName(child, className)) {
                    elements.push(child);
                }
            }
            return elements;
        } else {
            return children;
        }
    },
    getElementsByClassName: function(className, parent) {
        if (typeof(parent) == 'undefined') parent = document;
        var ret = [];
        if (!className) return ret;
        (function(parent) {
            var elems = parent.childNodes;
            for (var i = 0; i < elems.length; i++) {
                var e = elems[i];
                if (Ten.DOM.hasClassName(e, className)) {
                    ret.push(e);
                }
                arguments.callee(e);
            }
        })(parent);
        ret = Ten.Array.flatten(ret);
        return ret;
    },
    hasClassName: function(element, className) {
        if (!element || !className) return;
        var cname = element.className;
        if (!cname) return false;
        var cnames = cname.split(/\s+/);
        className = className.toLowerCase();
        for (var i = 0; i < cnames.length; i++) {
            if (cnames[i].toLowerCase() == className) {
                return true;
            }
        }
    },
    removeEmptyTextNodes: function(element) {
        var nodes = element.childNodes;
        for (var i = 0; i < nodes.length; i++) {
            var node = nodes[i];
            if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) {
                node.parentNode.removeChild(node);
            }
        }
    },
    nextElement: function(elem) {
        do {
            elem = elem.nextSibling;
        } while (elem && elem.nodeType != 1);
        return elem;
    },
    prevElement: function(elem) {
        do {
            elem = elem.previousSibling;
        } while (elem && elem.nodeType != 1);
        return elem;
    },
    insertBefore: function(node, ref) {
        ref.parentNode.insertBefore(node, ref);
    },
    insertAfter: function(node, ref) {
        if (ref.nextSibling) {
            ref.parentNode.insertBefore(node, ref.nextSibling);
        } else {
            ref.parentNode.appendChild(node);
        }
    },
    replaceNode: function(newNode, oldNode) {
        Ten.DOM.insertBefore(newNode, oldNode);
        oldNode.parentNode.removeChild(oldNode);
    },
    scrapeText: function(node) {
        var rval = [];
        (function (node) {
            var cn = node.childNodes;
            if (cn) {
                for (var i = 0; i < cn.length; i++) {
                    arguments.callee.call(this, cn[i]);
                }
            }
            var nodeValue = node.nodeValue;
            if (typeof(nodeValue) == 'string') {
                rval.push(nodeValue);
            }
        })(node);
        return rval.join('');
    },
    getSelectedText: function() {
        if (window.getSelection)
            return window.getSelection().toString() || '';
        else if (document.getSelection)
            return document.getSelection();
        else if (document.selection)
            return document.selection.createRange().text;
        else
            return '';
    },
    show: function(elem) {
        elem.style.display = 'block';
    },
    hide: function(elem) {
        elem.style.display = 'none';
    },
    onLoadFunctions: [],
    loaded: false,
    timer: null,
    addEventListener: function(event,func) {
        if (event != 'load') return;
        Ten.DOM.onLoadFunctions.push(func);
        Ten.DOM.checkLoaded();
    },
    checkLoaded: function() {
        var c = Ten.DOM;
        if (c.loaded) return true;
        if (document && document.getElementsByTagName &&
            document.getElementById && document.body) {
            if (c.timer) {
                clearInterval(c.timer);
                c.timer = null;
            }
            for (var i = 0; i < c.onLoadFunctions.length; i++) {
                c.onLoadFunctions[i]();
            }
            c.onLoadFunctions = [];
            c.loaded = true;
        } else {
            c.timer = setInterval(c.checkLoaded, 13);
        }
    }
});

/* Ten.Array */
Ten.Array = new Ten.Class({
    flatten: function(arr) {
        var ret = [];
        (function(arr) {
            for (var i = 0; i < arr.length; i++) {
                var o = arr[i];
                if (Ten.Array.isArray(o)) {
                    arguments.callee(o);
                } else {
                    ret.push(o);
                }
            }
        })(arr);
        return ret;
    },
    isArray: function(o) {
        return (o instanceof Array ||
                (o && typeof(o.length) === 'number' && typeof(o) != 'string'));
    }
});

/* Ten.Selector */
Ten.Selector = new Ten.Class({
    initialize: function(selector) {
        this.selectorText = selector;
        var sels = selector.split(/\s+/);
        var child = null;
        var separator = null;
        for (var i = sels.length - 1; i >= 0; i--) {
            if (sels[i] == '>') {
                continue;
            } else if ((i > 0) && sels[i-1] == '>') {
                separator = sels[i-1];
            }
            var opt = separator ? {separator: separator} : null;
            separator = null;
            var node = new Ten.SelectorNode(sels[i],child,opt);
            child = node;
        }
        this.childNode = child;
    },
    getElementsBySelector: function(selector, parent) {
        sels = selector.split(/\s*,\s*/);
        var ret = [];
        for (var i = 0; i < sels.length; i++) {
            var sel = new Ten.Selector(sels[i]);
            ret = ret.concat(sel.getElements(parent));
        }
        ret = Ten.Array.flatten(ret);
        return ret;
    }
},{
    getElements: function(parent) {
        if (typeof(parent) == 'undefined') {
            parent = document;
        }
        return this.childNode.getElements(parent);
    }
});

/* Ten.SelectorNode */
Ten.SelectorNode = new Ten.Class({
    initialize: function(selector, child, opt) {
        if (selector) {
            selector = selector.replace(/\s/g,'');
        }
        this.option = opt;
        this.selectorText = selector;
        this.childNode = child;
        this.parseSelector();
    }
},{
    getElementsBySelector: null, // will be overridden by parser
    parseSelector: function() {
        var f = 'getElementsBySelector';
        var t = this.selectorText;
        var match;
        if (match = t.match(/^(.+)\:([\w-+()]+)$/)) {
            t = match[1];
            this.pseudoClass = match[2];
        }
        if (t.match(/^[\w-]+$/)) {
            this[f] = function(parent) {
                return parent.getElementsByTagName(t);
            };
        } else if (match = t.match(/^([\w-]+)?#([\w-]+)$/)) {
            var tname = match[1];
            var idname = match[2];
            this[f] = function(parent) {
                var e = document.getElementById(idname);
                if (!tname ||
                    e.tagName.toLowerCase() == tname.toLowerCase()) {
                        return [e];
                    } else {
                        return [];
                    }
            };
        } else if (match = t.match(/^([\w-]+)?\.([\w-]+)/)) {
            var tname = match[1];
            var cname = match[2];
            this[f] = function(parent) {
                return Ten.DOM.getElementsByTagAndClassName(tname,cname,parent);
            };
        }
        if (this.option && this.option.separator) this.parseSeparator();
        if (this.pseudoClass) this.parsePseudoClass();
    },
    parsePseudoClass: function() {
        if (!this.pseudoClass) return;
        var pseudo = this.pseudoClass;
        var f = 'getElementsBySelector';
        var func = this[f];
        var match;
        if (match = pseudo.match(/^(.+)-child(\((\d+)\))?$/)) {
            var type = match[1];
            var n = match[3];
            var index;
            if (type == 'first') {
                index = 0;
            } else if (type == 'last') {
                index = -1;
            } else if (type == 'nth' && n) {
                index = n - 1;
            }
            if (typeof index == 'number') {
                this[f] = function(parent) {
                    var elems = func(parent);
                    if (index < 0) index = elems.length + index;
                    if (elems[index]) {
                        return [elems[index]];
                    } else {
                        return [];
                    }
                }
            }
        } else if (match = pseudo.match(/^nth-child\((\d+)n\+(\d+)\)$/)) {
            var a = new Number(match[1]);
            var b = new Number(match[2]);
            this[f] = function(parent) {
                var elems = func(parent);
                var ret = [];
                for (var n = 0; n < 1000; n++) {
                    var i = a * n + b - 1;
                    if (i < 0) continue;
                    if (typeof elems[i] == 'undefined') break;
                    ret.push(elems[i]);
                }
                return ret;
            };
        }
    },
    parseSeparator: function() {
        if (!this.option) return;
        var sep = this.option.separator;
        if (!sep) return;
        var f = 'getElementsBySelector';
        var func = this[f];
        if (sep == '>') {
            this[f] = function(parent) {
                var elems = func(parent);
                var childs = parent.childNodes;
                var ret = [];
                var j0 = 0;
                for (var i = 0; i < elems.length; i++) {
                    for (var j = j0; j < childs.length; j++) {
                        if (elems[i] == childs[j]) {
                            ret.push(elems[i]);
                            j0 = j + 1;
                            break;
                        }
                    }
                }
                return ret;
            }
        }
    },
    getElements: function(parent) {
        if (typeof this.getElementsBySelector != 'function') return;
        var ret = [];
        var elems = this.getElementsBySelector(parent);
        if (elems && this.childNode) {
            for (var i = 0; i < elems.length; i++) {
                ret.push(this.childNode.getElements(elems[i]));
            }
            return ret;
        } else {
            return elems;
        }
    }
});

/* Ten.Color */
Ten.Color = new Ten.Class({
    initialize: function(r,g,b,a) {
        if (typeof(a) == 'undefined' || a === null) a = 1;
        this.r = r;
        this.g = g;
        this.b = b;
        this.a = a;
    },
    parseFromString: function(str) {
        var match;
        if (match = str.match(/^#([0-9a-f]{6}|[0-9a-f]{3})$/i)) {
            var hexstr = match[1];
            var w = hexstr.length / 3;
            var rgb = [];
            for (var i = 0; i < 3; i++) {
                var hex = hexstr.substr(w * i, w);
                if (hex.length == 1) hex += hex;
                rgb.push(parseInt(hex,16));
            }
            return new Ten.Color(rgb[0],rgb[1],rgb[2]);
        } else if (match = str.match(/^rgb\(([\d.,\s]+)\)/)) {
            var rdba = match[1].split(/[\s,]+/);
            return new Ten.Color(rdba[0],rdba[1],rdba[2],rdba[3]);
        }
        return null;
    },
    parseFromElementColor: function(elem,prop) {
        var ret;
        for (var color; elem; elem = elem.parentNode) {
            color = Ten.Style.getElementStyle(elem, prop);
            if (typeof(color) != 'undefined' && color != 'transparent') {
                ret = color;
                break;
            }
        }
        return ret ? Ten.Color.parseFromString(ret) : null;
    }
},{
    asRGBString: function() {
        if (this.a < 1) {
            return 'rgba(' + this.r + ',' + this.g + ',' + this.b +
                ',' + this.a + ')';
        } else {
            return 'rgb(' + this.r + ',' + this.g + ',' + this.b + ')';
        }
    },
    asHexString: function() {
        var str = '#';
        var cls = ['r','g','b'];
        for (var i = 0; i < 3; i ++) {
            var c = Math.round(this[cls[i]]);
            var s = c.toString(16);
            if (c < 16) s = '0' + s;
            str += s;
        }
        return str;
    },
    overlay: function(color) {
        if (color.a == 1) return color;
        r = Math.round(color.r * color.a + this.r * this.a * (1 - color.a));
        g = Math.round(color.g * color.a + this.g * this.a * (1 - color.a));
        b = Math.round(color.b * color.a + this.b * this.a * (1 - color.a));
        return new Ten.Color(r,g,b);
    }
});

/* Ten.Style */
Ten.Style = new Ten.Class({
    applyStyle: function(elem, style) {
        for (prop in style) {
            elem.style[prop] = style[prop];
        }
    },
    getGlobalRule: function(selector) {
        selector = selector.toLowerCase();
        if (Ten.Style._cache[selector]) {
            return Ten.Style._cache[selector];
        } else if (Ten.Style._cache[selector] === null) {
            return null;
        } else {
            for (var i = document.styleSheets.length - 1; i >= 0; i--) {
                var ss = document.styleSheets[i];
                try {
                    var cssRules = ss.cssRules || ss.rules;
                } catch(e) {
                    continue;
                }
                for (var j = cssRules.length - 1; j >= 0; j--) {
                    var rule = cssRules[j];
                    if (rule.selectorText &&
                        rule.selectorText.toLowerCase() == selector) {
                            Ten.Style._cache[selector] = rule;
                            return rule;
                        }
                }
            }
        }
        Ten.Style._cache[selector] = null;
        return null;
    },
    getGlobalStyle: function(selector, prop) {
        var rule = Ten.Style.getGlobalRule(selector);
        if (rule && rule.style[prop]) {
            return rule.style[prop];
        } else {
            return null;
        }
    },
    getElementStyle: function(elem, prop) {
        var style = elem.style ? elem.style[prop] : null;
        if (!style) {
            var dv = document.defaultView;
            if (dv && dv.getComputedStyle) {
                try {
                    var styles = dv.getComputedStyle(elem, null);
                } catch(e) {
                    return null;
                }
                prop = prop.replace(/([A-Z])/g, '-$1').toLowerCase();
                style = styles ? styles.getPropertyValue(prop) : null;
            } else if (elem.currentStyle) {
                style = elem.currentStyle[prop];
            }
        }
        return style;
    },
    scrapeURL: function(url) {
        if (url.match(/url\((.+)\)/)) {
            url = RegExp.$1;
            url = url.replace(/['"<>]/g, '');
            return url;
        }
        return null;
    },
    _cache: {}
});

/* Ten.Geometry */
Ten.Geometry = new Ten.Class({
    initialize: function() {
        if (Ten.Geometry._initialized) return;
        var func = Ten.Geometry._functions;
        var de = document.documentElement;
        if (window.innerWidth) {
            func.getWindowWidth = function() { return window.innerWidth; }
            func.getWindowHeight = function() { return window.innerHeight; }
            func.getXScroll = function() { return window.pageXOffset; }
            func.getYScroll = function() { return window.pageYOffset; }
        } else if (de && de.clientWidth) {
            func.getWindowWidth = function() { return de.clientWidth; }
            func.getWindowHeight = function() { return de.clientHeight; }
            func.getXScroll = function() { return de.scrollLeft; }
            func.getYScroll = function() { return de.scrollTop; }
        } else if (document.body.clientWidth) {
            func.getWindowWidth = function() { return document.body.clientWidth; }
            func.getWindowHeight = function() { return document.body.clientHeight; }
            func.getXScroll = function() { return document.body.scrollLeft; }
            func.getYScroll = function() { return document.body.scrollTop; }
        }
        Ten.Geometry._initialized = true;
    },
    _initialized: false,
    _functions: {},
    getScroll: function() {
        if (!Ten.Geometry._initialized) new Ten.Geometry;
        return {
            x: Ten.Geometry._functions.getXScroll(),
            y: Ten.Geometry._functions.getYScroll()
        };
    },
    getMousePosition: function(pos) {
        // pos should have clientX, clientY same as mouse event
        if ((navigator.userAgent.indexOf('Safari') > -1) &&
            (navigator.userAgent.indexOf('Version/') < 0)) {
            return {
                x: pos.clientX,
                y: pos.clientY
            };
        } else {
            var scroll = Ten.Geometry.getScroll();
            return {
                x: pos.clientX + scroll.x,
                y: pos.clientY + scroll.y
            };
        }
    },
    getElementPosition: function(e) {
        return {
            x: e.offsetLeft,
            y: e.offsetTop
        };
    },
    getWindowSize: function() {
        if (!Ten.Geometry._initialized) new Ten.Geometry;
        return {
            w: Ten.Geometry._functions.getWindowWidth(),
            h: Ten.Geometry._functions.getWindowHeight()
        };
    }
});

/* Ten.Position */
Ten.Position = new Ten.Class({
    initialize: function(x,y) {
        this.x = x;
        this.y = y;
    },
    add: function(a,b) {
        return new Ten.Position(a.x + b.x, a.y + b.y);
    },
    subtract: function(a,b) {
        return new Ten.Position(a.x - b.x, a.y - b.y);
    }
});

EmberlynnEmberlynn 2011/07/23 18:16 I really wish there were more aicrtles like this on the web.

piumdgibsbpiumdgibsb 2011/07/24 23:38 gG8LTr , [url=http://toxlkdypogau.com/]toxlkdypogau[/url], [link=http://cdfqodqyansm.com/]cdfqodqyansm[/link], http://yoklmpzjcfxe.com/

fzadifxfzadifx 2011/07/26 19:13 5n2oon <a href="http://mtwptdcqccjk.com/">mtwptdcqccjk</a>

qrvluqdqrvluqd 2011/07/26 23:29 bm59Pf , [url=http://aewkxeueuebx.com/]aewkxeueuebx[/url], [link=http://ebcwefwnxaci.com/]ebcwefwnxaci[/link], http://lelmnzwofuep.com/

SlipsSlips 2013/03/31 17:44 That's a subtle way of tnhkinig about it.

jinicvjinicv 2013/04/02 01:18 7T3p9q , [url=http://vasxrovzugjn.com/]vasxrovzugjn[/url], [link=http://wgwxzjfkghjl.com/]wgwxzjfkghjl[/link], http://jxbsftdquicf.com/

bhxbbvqozzhbhxbbvqozzh 2013/04/02 07:47 vnQV5g <a href="http://bcuqqpryjcje.com/">bcuqqpryjcje</a>

jvjgfvjvjgfv 2013/04/04 19:19 pMU6nL , [url=http://mkljjgqyltsl.com/]mkljjgqyltsl[/url], [link=http://dfmpnvtzwing.com/]dfmpnvtzwing[/link], http://hmqruhnkigjm.com/

MauveMauve 2016/04/29 12:10 Although along with its reputation came up this speculations concerning their adverse reactions. The idea is when something is always that beneficial, then there must be something from the factor that can bring the alternative response. This is often one of the thought processes the novsco--ontinced consumers intend.

EmmaEmma 2016/05/03 12:47 Celso Azevedo • 31 de Janeiro de 2011 às 20:45Olá <a href="http://edftxaqryx.com">Gae,nblriifelizmente</a> eu também não uso nenhum metodo de pagamento usado aí noBrasil, só mesmo PayPal e por isso não posso ajuda-lo

TeiyaTeiya 2016/05/03 20:17 Elienai Luciano / Preliminares parece desculpa pra obter atenção. Eu apenas pergunto a ela, está pronta?, e a noite é sempre das.qlasuGoetei deste comentário ou não: 0 http://qurbbiuy.com [url=http://labmxxqkf.com]labmxxqkf[/url] [link=http://vryfha.com]vryfha[/link]

JamPlaycleJamPlaycle 2017/05/08 00:00 Viagra Ointment On Sale Sleepwell Worldwide Zentel 400mg Amex Real Order Kamagra Ireland Que Es Cialis Y Viagra Amitriptyline Overnight [url=http://byuvaigranonile.com]viagra[/url] Achetez Priligy 30 Mg Entrega Rapida Keflex Sulfa The Most Inexpensive Cialis Deals Propecia

KennFeceVietKennFeceViet 2017/06/23 20:57 Viagra A Poco Prezzo [url=http://doxycycline.ccrpdc.com/cheap-vibramycin-fast.php]Cheap Vibramycin Fast[/url] Honeymoon Cystitis Keflex Cheapeast Macrobid Ups No Prescription [url=http://levitra-buying.buylevi.com]Levitra Buying[/url] Prix Du Viagra Forum Viagra Kosten Mit Rezept [url=http://cial40mg.com/fast-delivery-cialis.php]Fast Delivery Cialis[/url] Propecia Halcon Viagra Generico Italia Si Puo Avere [url=http://cheap-generic-viagra.via100mg.com]Cheap Generic Viagra[/url] Viagra Frei Verkauflich 2013

AddtarkAddtark 2018/04/25 23:46 Cialis Cher [url=http://ciali5mg.com]generic cialis[/url] Viagra Buy Canada Rx Where Can I Buy Macrobid Bacterial Infections

DonnieatoveDonnieatove 2018/07/17 05:06 Gеt up tо $ 20,000 per dаy with our prоgrаm.
Wе аre а tеаm of expеrienсed prоgrаmmers, workеd morе thаn 14 mоnths оn this рrоgrаm and nоw еverything is rеadу аnd еvеrything wоrks pеrfectly. The РауPal sуstem is very vulnerable, instеаd of nоtifying the developеrs of РауРаl аbout this vulnеrаbility, we took advаntаgе оf it. We activelу usе our program for рersоnal еnriсhmеnt, tо shоw huge аmоunts оf mоney оn оur aссоunts, wе will nоt. you will not beliеvе until уou try аnd аs it is nоt in оur intеrest tо рrоve tо уou that sоmеthing is in уours. When we realizеd that this vulnеrаbilitу can bе usеd mаssivеlу withоut cоnsеquеnсes, wе dеcided tо help the rеst оf the рeорle. We dеcided nоt to inflаtе the priсе оf this gold рrogram аnd put a vеrу lоw рricе tag, only $ 550. In оrder for this progrаm tо bе аvаilable tо a largе numbеr оf pеople.
Аll the dеtails on оur blog: http://smart60.ru/go.php?url=https://www.pinterest.com/pin/690387817853172731/

DonnieatoveDonnieatove 2018/07/17 13:24 Gеt up to $ 20,000 рer day with оur рrogrаm.
We are a tеаm of expеriеnсed рrоgrammеrs, wоrkеd mоrе than 14 months оn this prоgram аnd now everything is reаdу and еverything works perfectlу. The РаyPal system is vеrу vulnerable, instеаd of nоtifying thе dеvеlopers of PaуPаl аbоut this vulnеrabilitу, wе tоok advantagе of it. Wе асtivеly use оur progrаm for реrsonаl еnrichmеnt, tо show huge аmоunts оf moneу on our ассounts, wе will not. уоu will not bеlieve until you trу аnd as it is not in оur intеrеst tо рrоvе to you thаt something is in yоurs. When wе realizеd thаt this vulnеrabilitу can bе usеd massivеly without сonsеquеnces, wе decidеd to hеlp the rest of thе peоplе. We dеcided nоt to inflаtе thе priсе of this gold progrаm and put a verу low priсе tаg, оnlу $ 550. In оrdеr fоr this prоgrаm tо bе аvаilаble to a largе number оf рeoрlе.
All the dеtails оn our blоg: http://skoli.ru/go?https://www.pinterest.com/pin/690387817853172731/

JamesCesteJamesCeste 2018/08/05 21:07 Help Jack please: http://ads.specificmedia.com/click/v=5%3Bm=2%3Bl=23470%3Bc=146418%3Bb=874880%3Bp=ui=ACXqoRFLEtwSFA%3Btr=DZeqTyQW0qH%3Btm=0-0%3Bts=20110427233838%3Bdct=https://vk.cc/8l7kvh

ptaletybkaptaletybka 2018/08/07 04:03 [url=http://bakerssign.com]order levitra online[/url] levitra prices walmart http://bakerssign.com

ftaletuglyftaletugly 2018/08/07 19:25 [url=http://motechautomotive.com]cheap cialis canadian[/url] generic cialis online pharmacy http://motechautomotive.com

vtaletjbmuvtaletjbmu 2018/08/08 18:58 [url=http://baymontelreno.com]how to buy cialis online[/url] buy cialis online http://baymontelreno.com

italetvkotitaletvkot 2018/08/18 09:06 [url=http://mphasset.com]how much does viagra cost without insurance[/url] viagra direct http://mphasset.com

htaletrfvghtaletrfvg 2018/08/18 14:13 [url=http://bakerssign.com]cost levitra[/url] cheapest levitra http://bakerssign.com

ataletqhmbataletqhmb 2018/08/18 18:20 [url=http://rabbitinahat.com]viagra levitra cialis[/url] cialis works best http://rabbitinahat.com

gtaletaivhgtaletaivh 2018/08/18 21:57 [url=http://gigawatt6.com]how long does it take cialis 5mg to work[/url] best website to buy cialis http://gigawatt6.com

wtaletxpeowtaletxpeo 2018/08/19 01:09 [url=http://missreplicawatches.com]prostatitis cialis[/url] cialis product monograph http://missreplicawatches.com

dtalettnuydtalettnuy 2018/08/19 04:21 [url=http://missreplicawatches.com]cialis price per pill[/url] counterfeit cialis pictures http://missreplicawatches.com

htaletpymthtaletpymt 2018/08/19 15:43 [url=http://bakerssign.com]uses for levitra[/url] levitra 20mg uk http://bakerssign.com

gtaletzdzpgtaletzdzp 2018/08/19 18:29 [url=http://missreplicawatches.com]online cialis store[/url] when should you take cialis http://missreplicawatches.com

ftalethdagftalethdag 2018/09/11 12:27 [url=http://gigawatt6.com]which is better viagra cialis or levitra[/url] cialis how long does it last http://gigawatt6.com

ntaletnbyfntaletnbyf 2018/09/11 15:25 [url=http://mphasset.com]generic for viagra name[/url] adverse effects of viagra http://mphasset.com

gtaletiprtgtaletiprt 2018/09/11 22:33 [url=http://gigawatt6.com]how to take cialis 20mg[/url] how fast does cialis 5mg work http://gigawatt6.com

ntaletugcbntaletugcb 2018/09/12 05:25 [url=http://missreplicawatches.com]buy real cialis[/url] order cialis from canadian pharmacy http://missreplicawatches.com

utaletvsvlutaletvsvl 2018/09/12 08:06 [url=http://viciolatino.com]viagra online paypal[/url] best online pharmacy for viagra http://viciolatino.com

wtaletmuxjwtaletmuxj 2018/09/12 14:54 [url=http://gigawatt6.com]cheap cialis black[/url] cheap cialis 20 mg http://gigawatt6.com

ztaletnhfxztaletnhfx 2018/09/12 16:55 [url=http://canadian-pharmabuy.com]viagra prices[/url] buy viagra 100mg http://canadian-pharmabuy.com

vtalethlumvtalethlum 2018/09/12 22:09 [url=http://buycialisonl1ne.us]cheap cialis sale online[/url] cialis 5 mg http://buycialisonl1ne.us

ftaletwqzvftaletwqzv 2018/09/13 00:09 [url=http://missreplicawatches.com]buy cialis with prescription[/url] cialis online with prescription http://missreplicawatches.com

ataletvgseataletvgse 2018/09/13 04:24 [url=http://rabbitinahat.com]viagra cialis online[/url] cialis canada http://rabbitinahat.com

ztaletqhtvztaletqhtv 2018/09/13 08:53 [url=http://motechautomotive.com]cheap cialis uk[/url] cialis for sale cheap http://motechautomotive.com

qtaletqkyaqtaletqkya 2018/09/13 09:28 [url=http://gigawatt6.com]order cialis online us[/url] order cialis no prescription http://gigawatt6.com

ftaletfqryftaletfqry 2018/09/13 22:04 [url=http://motechautomotive.com]canadian online pharmacy generic cialis[/url] order generic cialis online canada http://motechautomotive.com

vtaletamtyvtaletamty 2018/09/14 01:59 [url=http://rabbitinahat.com]how to buy cialis online[/url] order 5mg cialis http://rabbitinahat.com

jtalettqqujtalettqqu 2018/09/14 04:36 [url=http://canadian-pharmasale.com]can you order cialis online[/url] cialis online http://canadian-pharmasale.com

ctaletrrsuctaletrrsu 2018/09/14 15:42 [url=http://usedrestaurantequipmentaz.com]cheap brand cialis online[/url] order cialis from india http://usedrestaurantequipmentaz.com

gtaletumpsgtaletumps 2018/09/15 08:19 [url=http://usedrestaurantequipmentaz.com]order generic cialis online canada[/url] order cialis online canadian pharmacy http://usedrestaurantequipmentaz.com

staletiywqstaletiywq 2018/09/15 09:46 [url=http://valladium.com]cheap cialis in canada[/url] order generic cialis http://valladium.com

qtaletdtujqtaletdtuj 2018/09/15 18:48 [url=http://top-monterey-salinas-dentists.com]what does levitra do[/url] levitra 20mg tablets http://top-monterey-salinas-dentists.com

xtaletloqrxtaletloqr 2018/09/16 00:32 [url=http://buyviagraonl1ne.us]viagra for sale online cheap[/url] cheap viagra online pharmacy http://buyviagraonl1ne.us

htaletwonnhtaletwonn 2018/09/16 15:35 [url=http://top-monterey-salinas-dentists.com]how long does it take for levitra to work[/url] viagra cialis levitra http://top-monterey-salinas-dentists.com

btaletytfbbtaletytfb 2018/09/16 22:44 [url=http://baymontelreno.com]order cialis no prescription[/url] buy cialis http://baymontelreno.com

utaletorujutaletoruj 2018/09/17 02:50 [url=http://bullsac.com]levitra online canada[/url] levitra pill http://bullsac.com

ttaletqfwzttaletqfwz 2018/09/17 07:17 [url=http://unishade.com]order cialis usa[/url] cheap cialis prices http://unishade.com

qtaletjzvhqtaletjzvh 2018/09/17 11:57 [url=http://buyviagraonl1ne.us]buy viagra in canada[/url] viagra online canada http://buyviagraonl1ne.us

ptaletsjjtptaletsjjt 2018/09/17 15:47 [url=http://top-monterey-salinas-dentists.com]levitra coupon 3 free pills[/url] levitra super force http://top-monterey-salinas-dentists.com

jtaletbfkcjtaletbfkc 2018/09/17 20:18 [url=http://waltzweekend.com]cheap viagra canada pharmacy[/url] generic viagra online canadian pharmacy http://waltzweekend.com

wtaletmnniwtaletmnni 2018/09/18 05:29 [url=http://canadian-pharmabuy.com]generic viagra online usa[/url] generic viagra usa http://canadian-pharmabuy.com

ftaletwmmoftaletwmmo 2018/09/18 15:12 [url=http://canadian-pharmaonline.com]cheap viagra 100mg[/url] generic viagra online http://canadian-pharmaonline.com

jtaletviejjtaletviej 2018/09/19 00:57 [url=http://valladium.com]buy cialis online with prescription[/url] cialis price http://valladium.com

ktaletbemuktaletbemu 2018/09/19 09:47 [url=http://top-monterey-salinas-dentists.com]cost of levitra per pill[/url] levitra brand online http://top-monterey-salinas-dentists.com

gtaletftzegtaletftze 2018/09/19 10:48 [url=http://motechautomotive.com]cialis online bestellen[/url] cialis coupons online http://motechautomotive.com

mtaletsiwymtaletsiwy 2018/09/19 11:24 [url=http://gigawatt6.com]cheap cialis uk[/url] generic cialis for sale http://gigawatt6.com

btaletskrjbtaletskrj 2018/09/19 21:00 [url=http://buycialisonlineglka.com]cheap brand cialis online[/url] generic cialis 60 mg http://buycialisonlineglka.com

qtaletaajcqtaletaajc 2018/09/19 21:57 [url=http://valladium.com]cialis pill[/url] generic cialis for order http://valladium.com

otaletcmudotaletcmud 2018/09/19 22:27 [url=http://viciolatino.com]buy viagra canada[/url] cheapest generic viagra online http://viciolatino.com

ゲスト



トラックバック - http://javascript.g.hatena.ne.jp/Yuichirou/20071002