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);
    }
});

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

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

fzadifxfzadifx2011/07/26 19:135n2oon <a href="http://mtwptdcqccjk.com/">mtwptdcqccjk</a>

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

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

jinicvjinicv2013/04/02 01:187T3p9q , [url=http://vasxrovzugjn.com/]vasxrovzugjn[/url], [link=http://wgwxzjfkghjl.com/]wgwxzjfkghjl[/link], http://jxbsftdquicf.com/

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

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

MauveMauve2016/04/29 12:10Although 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.

EmmaEmma2016/05/03 12:47Celso 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

TeiyaTeiya2016/05/03 20:17Elienai 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]

JamPlaycleJamPlaycle2017/05/08 00:00Viagra 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

KennFeceVietKennFeceViet2017/06/23 20:57Viagra 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

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

DonnieatoveDonnieatove2018/07/17 05:06Gе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/

DonnieatoveDonnieatove2018/07/17 13:24Gе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/

JamesCesteJamesCeste2018/08/05 21:07Help 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

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

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

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

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

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

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

gtaletaivhgtaletaivh2018/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

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

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

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

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

ftalethdagftalethdag2018/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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

qtaletdtujqtaletdtuj2018/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

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

htaletwonnhtaletwonn2018/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

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

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

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

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

ptaletsjjtptaletsjjt2018/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

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

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

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

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

ktaletbemuktaletbemu2018/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

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

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

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

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

otaletcmudotaletcmud2018/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