<commit_before>/* vim:ts=4:sts=4:sw=4:
 * ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is Ajax.org Code Editor (ACE).
 *
 * The Initial Developer of the Original Code is
 * Ajax.org B.V.
 * Portions created by the Initial Developer are Copyright (C) 2010
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *      Fabian Jakobs <fabian AT ajax DOT org>
 *      Julian Viereck <julian.viereck@gmail.com>
 *      Mihai Sucan <mihai.sucan@gmail.com>
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

define(function(require, exports, module) {

var oop = require("pilot/oop");
var dom = require("pilot/dom");
var lang = require("pilot/lang");
var EventEmitter = require("pilot/event_emitter").EventEmitter;

var Text = function(parentEl) {
    this.element = dom.createElement("div");
    this.element.className = "ace_layer ace_text-layer";
    parentEl.appendChild(this.element);

    this.$characterSize = this.$measureSizes();
    this.$pollSizeChanges();
};

(function() {

    oop.implement(this, EventEmitter);

    this.EOF_CHAR = "¶";
    this.EOL_CHAR = "¬";
    this.TAB_CHAR = "→";
    this.SPACE_CHAR = "·";

    this.setTokenizer = function(tokenizer) {
        this.tokenizer = tokenizer;
    };

    this.getLineHeight = function() {
        return this.$characterSize.height || 1;
    };

    this.getCharacterWidth = function() {
        return this.$characterSize.width || 1;
    };

    this.$pollSizeChanges = function() {
        var self = this;
        setInterval(function() {
            var size = self.$measureSizes();
            if (self.$characterSize.width !== size.width || self.$characterSize.height !== size.height) {
                self.$characterSize = size;
                self._dispatchEvent("changeCharaterSize", {data: size});
            }
        }, 500);
    };

    this.$fontStyles = {
        fontFamily : 1,
        fontSize : 1,
        fontWeight : 1,
        fontStyle : 1,
        lineHeight : 1
    },

    this.$measureSizes = function() {
        var n = 1000;
        if (!this.$measureNode) {
            var measureNode = this.$measureNode = dom.createElement("div");
            var style = measureNode.style;

            style.width = style.height = "auto";
            style.left = style.top = (-n * 40)  + "px";

            style.visibility = "hidden";
            style.position = "absolute";
            style.overflow = "visible";
            style.whiteSpace = "nowrap";

            // in FF 3.6 monospace fonts can have a fixed sub pixel width.
            // that's why we have to measure many characters
            // Note: characterWidth can be a float!
            measureNode.innerHTML = lang.stringRepeat("Xy", n);

            var container = this.element.parentNode;
            while (!dom.hasCssClass(container, "ace_editor"))
                container = container.parentNode;

            container.appendChild(measureNode);
        }

        var style = this.$measureNode.style;
        for (var prop in this.$fontStyles) {
            var value = dom.computedStyle(this.element, prop);
            style[prop] = value;
        }

        var size = {
            height: this.$measureNode.offsetHeight,
            width: this.$measureNode.offsetWidth / (n * 2)
        };
        return size;
    };

    this.setSession = function(session) {
        this.session = session;
    };

    this.showInvisibles = false;
    this.setShowInvisibles = function(showInvisibles) {
        if (this.showInvisibles == showInvisibles)
            return false;

        this.showInvisibles = showInvisibles;
        return true;
    };

    this.$computeTabString = function() {
        var tabSize = this.session.getTabSize();
        if (this.showInvisibles) {
            var halfTab = (tabSize) / 2;
            this.$tabString = ""
                + new Array(Math.floor(halfTab)).join(" ")
                + this.TAB_CHAR
                + new Array(Math.ceil(halfTab)+1).join(" ")
                + "";
        } else {
            this.$tabString = new Array(tabSize+1).join(" ");
        }
    };

    this.updateLines = function(config, firstRow, lastRow) {
        this.$computeTabString();
        // Due to wrap line changes there can be new lines if e.g.
        // the line to updated wrapped in the meantime.
        if (this.config.lastRow != config.lastRow ||
            this.config.firstRow != config.firstRow) {
            this.scrollLines(config);
        }
        this.config = config;

        var first = Math.max(firstRow, config.firstRow);
        var last = Math.min(lastRow, config.lastRow);

        var lineElements = this.element.childNodes;
        var tokens = this.tokenizer.getTokens(first, last);
        for (var i=first; i<=last; i++) {
            var lineElement = lineElements[i - config.firstRow];
            if (!lineElement)
                continue;

            var html = [];
            this.$renderLine(html, i, tokens[i-first].tokens);
            lineElement = dom.setInnerHtml(lineElement, html.join(""));
            lineElement.style.height =
                    this.session.getRowHeight(config, i) + "px";
        }
    };

    this.scrollLines = function(config) {
        this.$computeTabString();
        var oldConfig = this.config;
        this.config = config;

        if (!oldConfig || oldConfig.lastRow < config.firstRow)
            return this.update(config);

        if (config.lastRow < oldConfig.firstRow)
            return this.update(config);

        var el = this.element;

        if (oldConfig.firstRow < config.firstRow)
            for (var row=oldConfig.firstRow; row<config.firstRow; row++)
                el.removeChild(el.firstChild);

        if (oldConfig.lastRow > config.lastRow)
            for (var row=config.lastRow+1; row<=oldConfig.lastRow; row++)
                el.removeChild(el.lastChild);

        if (config.firstRow < oldConfig.firstRow) {
            var fragment = this.$renderLinesFragment(config, config.firstRow, oldConfig.firstRow - 1);
            if (el.firstChild)
                el.insertBefore(fragment, el.firstChild);
            else
                el.appendChild(fragment);
        }

        if (config.lastRow > oldConfig.lastRow) {
            var fragment = this.$renderLinesFragment(config, oldConfig.lastRow + 1, config.lastRow);
            el.appendChild(fragment);
        }
    };

    this.$renderLinesFragment = function(config, firstRow, lastRow) {
        var fragment = document.createDocumentFragment();
        var tokens = this.tokenizer.getTokens(firstRow, lastRow);
        for (var row=firstRow; row<=lastRow; row++) {
            var lineEl = dom.createElement("div");
            lineEl.className = "ace_line";
            var style = lineEl.style;
            style.height = this.session.getRowHeight(config, row) + "px";
            style.width = config.width + "px";

            var html = [];
            if (tokens.length > row-firstRow)
                this.$renderLine(html, row, tokens[row-firstRow].tokens);
            // don't use setInnerHtml since we are working with an empty DIV
            lineEl.innerHTML = html.join("");
            fragment.appendChild(lineEl);
        }
        return fragment;
    };

    this.update = function(config) {
        this.$computeTabString();
        this.config = config;

        var html = [];
        var tokens = this.tokenizer.getTokens(config.firstRow, config.lastRow)
        var fragment = this.$renderLinesFragment(config, config.firstRow, config.lastRow);

        // Clear the current content of the element and add the rendered fragment.
        this.element.innerHTML =  "";
        this.element.appendChild(fragment);
    };

    this.$textToken = {
        "text": true,
        "rparen": true,
        "lparen": true
    };

    this.$renderLine = function(stringBuilder, row, tokens) {
        if (this.showInvisibles) {
            var self = this;
            var spaceRe = /( +)|([\v\f \u00a0\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000])/g;
            var spaceReplace = function(space) {
                if (space.charCodeAt(0) == 32)
                    return new Array(space.length+1).join(" ");
                else {
                    var space = new Array(space.length+1).join(self.SPACE_CHAR);
                    return "" + space + "";
                }

            };
        }
        else {
            var spaceRe = /[\v\f \u00a0\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000]/g;
            var spaceReplace = " ";
        }

        var _self = this;
        var characterWidth = this.config.characterWidth;
        function addToken(token, value) {
            var output = value
                .replace(/&/g, "&")
                .replace(/</g, "<")
                .replace(spaceRe, spaceReplace)
                .replace(/\t/g, _self.$tabString)
                .replace(/[\u3040-\u309F]|[\u30A0-\u30FF]|[\u4E00-\u9FFF\uF900-\uFAFF\u3400-\u4DBF]/g, function(c) {
                    return "" + c + ""
                });

            if (!_self.$textToken[token.type]) {
                var classes = "ace_" + token.type.replace(/\./g, " ace_");
                stringBuilder.push("", output, "");
            }
            else {
                stringBuilder.push(output);
            }
        }

        var splits = this.session.getRowSplitData(row);
        var chars = 0, split = 0, splitChars;

        if (!splits || splits.length == 0) {
            splitChars = Number.MAX_VALUE;
        } else {
            splitChars = splits[0];
        }

        stringBuilder.push("
");
        for (var i = 0; i < tokens.length; i++) {
            var token = tokens[i];
            var value = token.value;

            if (chars + value.length < splitChars) {
                addToken(token, value);
                chars += value.length;
            } else {
                while (chars + value.length >= splitChars) {
                    addToken(token, value.substring(0, splitChars - chars));
                    value = value.substring(splitChars - chars);
                    chars = splitChars;
                    stringBuilder.push("
",
                        "
");
                    split ++;
                    splitChars = splits[split] || Number.MAX_VALUE;
                }
                if (value.length != 0) {
                    chars += value.length;
                    addToken(token, value);
                }
            }
        };

        if (this.showInvisibles) {
            if (row !== this.session.getLength() - 1) {
                stringBuilder.push("" + this.EOL_CHAR + "");
            } else {
                stringBuilder.push("" + this.EOF_CHAR + "");
            }
        }
        stringBuilder.push("
");
    };

}).call(Text.prototype);

exports.Text = Text;

});
<commit_msg>if possible append the measure node to the body to prevent flickering<commit_after>/* vim:ts=4:sts=4:sw=4:
 * ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is Ajax.org Code Editor (ACE).
 *
 * The Initial Developer of the Original Code is
 * Ajax.org B.V.
 * Portions created by the Initial Developer are Copyright (C) 2010
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *      Fabian Jakobs <fabian AT ajax DOT org>
 *      Julian Viereck <julian.viereck@gmail.com>
 *      Mihai Sucan <mihai.sucan@gmail.com>
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

define(function(require, exports, module) {

var oop = require("pilot/oop");
var dom = require("pilot/dom");
var lang = require("pilot/lang");
var EventEmitter = require("pilot/event_emitter").EventEmitter;

var Text = function(parentEl) {
    this.element = dom.createElement("div");
    this.element.className = "ace_layer ace_text-layer";
    parentEl.appendChild(this.element);

    this.$characterSize = this.$measureSizes();
    this.$pollSizeChanges();
};

(function() {

    oop.implement(this, EventEmitter);

    this.EOF_CHAR = "¶";
    this.EOL_CHAR = "¬";
    this.TAB_CHAR = "→";
    this.SPACE_CHAR = "·";

    this.setTokenizer = function(tokenizer) {
        this.tokenizer = tokenizer;
    };

    this.getLineHeight = function() {
        return this.$characterSize.height || 1;
    };

    this.getCharacterWidth = function() {
        return this.$characterSize.width || 1;
    };

    this.$pollSizeChanges = function() {
        var self = this;
        setInterval(function() {
            var size = self.$measureSizes();
            if (self.$characterSize.width !== size.width || self.$characterSize.height !== size.height) {
                self.$characterSize = size;
                self._dispatchEvent("changeCharaterSize", {data: size});
            }
        }, 500);
    };

    this.$fontStyles = {
        fontFamily : 1,
        fontSize : 1,
        fontWeight : 1,
        fontStyle : 1,
        lineHeight : 1
    },

    this.$measureSizes = function() {
        var n = 1000;
        if (!this.$measureNode) {
            var measureNode = this.$measureNode = dom.createElement("div");
            var style = measureNode.style;

            style.width = style.height = "auto";
            style.left = style.top = (-n * 40)  + "px";

            style.visibility = "hidden";
            style.position = "absolute";
            style.overflow = "visible";
            style.whiteSpace = "nowrap";

            // in FF 3.6 monospace fonts can have a fixed sub pixel width.
            // that's why we have to measure many characters
            // Note: characterWidth can be a float!
            measureNode.innerHTML = lang.stringRepeat("Xy", n);

            if (document.body) {
                document.body.appendChild(measureNode);
            } else {
                var container = this.element.parentNode;
                while (!dom.hasCssClass(container, "ace_editor"))
                    container = container.parentNode;
                container.appendChild(measureNode);
            }

        }

        var style = this.$measureNode.style;
        for (var prop in this.$fontStyles) {
            var value = dom.computedStyle(this.element, prop);
            style[prop] = value;
        }

        var size = {
            height: this.$measureNode.offsetHeight,
            width: this.$measureNode.offsetWidth / (n * 2)
        };
        return size;
    };

    this.setSession = function(session) {
        this.session = session;
    };

    this.showInvisibles = false;
    this.setShowInvisibles = function(showInvisibles) {
        if (this.showInvisibles == showInvisibles)
            return false;

        this.showInvisibles = showInvisibles;
        return true;
    };

    this.$computeTabString = function() {
        var tabSize = this.session.getTabSize();
        if (this.showInvisibles) {
            var halfTab = (tabSize) / 2;
            this.$tabString = ""
                + new Array(Math.floor(halfTab)).join(" ")
                + this.TAB_CHAR
                + new Array(Math.ceil(halfTab)+1).join(" ")
                + "";
        } else {
            this.$tabString = new Array(tabSize+1).join(" ");
        }
    };

    this.updateLines = function(config, firstRow, lastRow) {
        this.$computeTabString();
        // Due to wrap line changes there can be new lines if e.g.
        // the line to updated wrapped in the meantime.
        if (this.config.lastRow != config.lastRow ||
            this.config.firstRow != config.firstRow) {
            this.scrollLines(config);
        }
        this.config = config;

        var first = Math.max(firstRow, config.firstRow);
        var last = Math.min(lastRow, config.lastRow);

        var lineElements = this.element.childNodes;
        var tokens = this.tokenizer.getTokens(first, last);
        for (var i=first; i<=last; i++) {
            var lineElement = lineElements[i - config.firstRow];
            if (!lineElement)
                continue;

            var html = [];
            this.$renderLine(html, i, tokens[i-first].tokens);
            lineElement = dom.setInnerHtml(lineElement, html.join(""));
            lineElement.style.height =
                    this.session.getRowHeight(config, i) + "px";
        }
    };

    this.scrollLines = function(config) {
        this.$computeTabString();
        var oldConfig = this.config;
        this.config = config;

        if (!oldConfig || oldConfig.lastRow < config.firstRow)
            return this.update(config);

        if (config.lastRow < oldConfig.firstRow)
            return this.update(config);

        var el = this.element;

        if (oldConfig.firstRow < config.firstRow)
            for (var row=oldConfig.firstRow; row<config.firstRow; row++)
                el.removeChild(el.firstChild);

        if (oldConfig.lastRow > config.lastRow)
            for (var row=config.lastRow+1; row<=oldConfig.lastRow; row++)
                el.removeChild(el.lastChild);

        if (config.firstRow < oldConfig.firstRow) {
            var fragment = this.$renderLinesFragment(config, config.firstRow, oldConfig.firstRow - 1);
            if (el.firstChild)
                el.insertBefore(fragment, el.firstChild);
            else
                el.appendChild(fragment);
        }

        if (config.lastRow > oldConfig.lastRow) {
            var fragment = this.$renderLinesFragment(config, oldConfig.lastRow + 1, config.lastRow);
            el.appendChild(fragment);
        }
    };

    this.$renderLinesFragment = function(config, firstRow, lastRow) {
        var fragment = document.createDocumentFragment();
        var tokens = this.tokenizer.getTokens(firstRow, lastRow);
        for (var row=firstRow; row<=lastRow; row++) {
            var lineEl = dom.createElement("div");
            lineEl.className = "ace_line";
            var style = lineEl.style;
            style.height = this.session.getRowHeight(config, row) + "px";
            style.width = config.width + "px";

            var html = [];
            if (tokens.length > row-firstRow)
                this.$renderLine(html, row, tokens[row-firstRow].tokens);
            // don't use setInnerHtml since we are working with an empty DIV
            lineEl.innerHTML = html.join("");
            fragment.appendChild(lineEl);
        }
        return fragment;
    };

    this.update = function(config) {
        this.$computeTabString();
        this.config = config;

        var html = [];
        var tokens = this.tokenizer.getTokens(config.firstRow, config.lastRow)
        var fragment = this.$renderLinesFragment(config, config.firstRow, config.lastRow);

        // Clear the current content of the element and add the rendered fragment.
        this.element.innerHTML =  "";
        this.element.appendChild(fragment);
    };

    this.$textToken = {
        "text": true,
        "rparen": true,
        "lparen": true
    };

    this.$renderLine = function(stringBuilder, row, tokens) {
        if (this.showInvisibles) {
            var self = this;
            var spaceRe = /( +)|([\v\f \u00a0\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000])/g;
            var spaceReplace = function(space) {
                if (space.charCodeAt(0) == 32)
                    return new Array(space.length+1).join(" ");
                else {
                    var space = new Array(space.length+1).join(self.SPACE_CHAR);
                    return "" + space + "";
                }

            };
        }
        else {
            var spaceRe = /[\v\f \u00a0\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000]/g;
            var spaceReplace = " ";
        }

        var _self = this;
        var characterWidth = this.config.characterWidth;
        function addToken(token, value) {
            var output = value
                .replace(/&/g, "&")
                .replace(/</g, "<")
                .replace(spaceRe, spaceReplace)
                .replace(/\t/g, _self.$tabString)
                .replace(/[\u3040-\u309F]|[\u30A0-\u30FF]|[\u4E00-\u9FFF\uF900-\uFAFF\u3400-\u4DBF]/g, function(c) {
                    return "" + c + ""
                });

            if (!_self.$textToken[token.type]) {
                var classes = "ace_" + token.type.replace(/\./g, " ace_");
                stringBuilder.push("", output, "");
            }
            else {
                stringBuilder.push(output);
            }
        }

        var splits = this.session.getRowSplitData(row);
        var chars = 0, split = 0, splitChars;

        if (!splits || splits.length == 0) {
            splitChars = Number.MAX_VALUE;
        } else {
            splitChars = splits[0];
        }

        stringBuilder.push("
");
        for (var i = 0; i < tokens.length; i++) {
            var token = tokens[i];
            var value = token.value;

            if (chars + value.length < splitChars) {
                addToken(token, value);
                chars += value.length;
            } else {
                while (chars + value.length >= splitChars) {
                    addToken(token, value.substring(0, splitChars - chars));
                    value = value.substring(splitChars - chars);
                    chars = splitChars;
                    stringBuilder.push("
",
                        "
");
                    split ++;
                    splitChars = splits[split] || Number.MAX_VALUE;
                }
                if (value.length != 0) {
                    chars += value.length;
                    addToken(token, value);
                }
            }
        };

        if (this.showInvisibles) {
            if (row !== this.session.getLength() - 1) {
                stringBuilder.push("" + this.EOL_CHAR + "");
            } else {
                stringBuilder.push("" + this.EOF_CHAR + "");
            }
        }
        stringBuilder.push("
");
    };

}).call(Text.prototype);

exports.Text = Text;

});
<|endoftext|>


<commit_before>const url = 'https://swapi.co/api/people/';
const searchButton = document.querySelector("#searchButton");
const searchResultsTable = document.querySelector("#itemlist");
const resultsResults = document.querySelector("#searchResults");
let data = null;
let planet = null;
let planetResidents = null;

const renderPersonsTable = (container, data) => {
	container.innerHTML = data.map((item, counter) =>
		`

			${data[counter].name}

`).join('');
}

const fetchPerson = (url) => {
	fetch(url)
		.then(data => data.json())
		.then(data=> {
			searchResultsTable.innerHTML = "";
			let result = data.results;
			renderPersonsTable(searchResultsTable, result);
			renderPersonDetails(".search-result a", searchResultsTable);
				if (data.next)
					fetchPerson(data.next);
		});
}
const fetchPlanetResidents = (homeworld) => {
	fetch(homeworld)
		.then(data => data.json())
		.then(data=> {
			planetResidents = data.residents;
			planet = data.name;
		});
}

const renderResidents = (container ,planetResidents) => {
	for(var key in planetResidents) {
	    if(planetResidents.hasOwnProperty(key)) {
	        console.log(planetResidents[key]);
	        let eachResident = planetResidents[key];
	        fetch(eachResident)
	        	.then(data => data.json())
	        	.then(data=> {
	        		console.log(data.name);
	        		console.log(data.url);
				container.innerHTML +=
				`

					${data.name}

`;
				renderPersonDetails(".search-result a", searchResultsTable);
	        	});
	    }
	}

}

const renderPersonDetails = (keyMapElement, searchResultsContainer) => {
	let keysMap = document.querySelectorAll(keyMapElement);
	for (key in keysMap) {
		keysMap[key].onclick = function(e) {
			e.preventDefault();
			let path = this.href;
			let renderPlanetResidents = null;
			fetch(path)
				.then(data => data.json())
				.then(data => {
					let {name, birth_year, gender, homeworld} = data;
					fetchPlanetResidents(homeworld);
					setTimeout(() => {
						searchResultsContainer.innerHTML =
							`

Name: ${name}

Birth Year: ${birth_year}

Gender: ${gender}

Planet: ${planet}

${planet} Residents:

`;
							let kek = document.querySelector('#renderResidentsTable');
							renderResidents(kek, planetResidents);
					}, 2000);
				});
		}
	}
}

window.onload = fetchPerson(url);
searchButton.addEventListener('click', (e) => {
  fetchPerson(url);
});

searchButton.addEventListener('mouseover', ()=>{
	let audio = new Audio();
	audio.src = '../src/js/sounds/open.mp4';
	audio.play();
	setTimeout(() => {
	  searchButton.innerText = `Welcome to the dark side`;
	}, 700)
});

searchButton.addEventListener('mouseout', ()=>{
	let audio = new Audio();
	audio.src = '../src/js/sounds/Close.mp4';
	audio.play();
	setTimeout(() => {
	  searchButton.innerText = `Go, Jedi !`;
	}, 700)
});<commit_msg>I finally made it!<commit_after>const url = 'https://swapi.co/api/people/';
const searchButton = document.querySelector("#searchButton");
const searchResultsTable = document.querySelector("#itemlist");
const resultsResults = document.querySelector("#searchResults");
let data = null;
let planet = null;
let planetResidents = null;

const renderPersonsTable = (container, data) => {
	container.innerHTML += data.map((item, counter) =>
		`

			${data[counter].name}

`).join('');
}

const fetchPerson = (url) => {
	fetch(url)
		.then(data => data.json())
		.then(data=> {
			let result = data.results;
			renderPersonsTable(searchResultsTable, result);
			renderPersonDetails(".search-result a", searchResultsTable);
				if (data.next)
					fetchPerson(data.next);
		});
}
const fetchPlanetResidents = (homeworld) => {
	fetch(homeworld)
		.then(data => data.json())
		.then(data=> {
			planetResidents = data.residents;
			planet = data.name;
		});
}

const renderResidents = (container ,planetResidents) => {
	for(var key in planetResidents) {
	    if(planetResidents.hasOwnProperty(key)) {
	        console.log(planetResidents[key]);
	        let eachResident = planetResidents[key];
	        fetch(eachResident)
	        	.then(data => data.json())
	        	.then(data=> {
	        		console.log(data.name);
	        		console.log(data.url);
				container.innerHTML +=
				`

					${data.name}

`;
				renderPersonDetails(".search-result a", searchResultsTable);
	        	});
	    }
	}

}

const renderPersonDetails = (keyMapElement, searchResultsContainer) => {
	let keysMap = document.querySelectorAll(keyMapElement);
	for (key in keysMap) {
		keysMap[key].onclick = function(e) {
			e.preventDefault();
			let path = this.href;
			let renderPlanetResidents = null;
			fetch(path)
				.then(data => data.json())
				.then(data => {
					let {name, birth_year, gender, homeworld} = data;
					fetchPlanetResidents(homeworld);
					setTimeout(() => {
						searchResultsContainer.innerHTML =
							`

Name: ${name}

Birth Year: ${birth_year}

Gender: ${gender}

Planet: ${planet}

${planet} Residents:

`;
							let kek = document.querySelector('#renderResidentsTable');
							renderResidents(kek, planetResidents);
					}, 2000);
				});
		}
	}
}

const cleaningPersonResult = (container)=>{
	container.innerHTML = "";
}

window.onload = fetchPerson(url);
searchButton.addEventListener('click', (e) => {
  cleaningPersonResult(searchResultsTable);
  fetchPerson(url);
});

searchButton.addEventListener('mouseover', ()=>{
	let audio = new Audio();
	audio.src = '../src/js/sounds/open.mp4';
	audio.play();
	setTimeout(() => {
	  searchButton.innerText = `Welcome to the dark side`;
	}, 700)
});

searchButton.addEventListener('mouseout', ()=>{
	let audio = new Audio();
	audio.src = '../src/js/sounds/Close.mp4';
	audio.play();
	setTimeout(() => {
	  searchButton.innerText = `Go, Jedi !`;
	}, 700)
});<|endoftext|>


<commit_before>describe("VglRenderer component", function() {
    const {VglRenderer, VglNamespace} = VueGL;
    const assert = chai.assert;
    const webgl = (() => {
        const canvas = document.createElement("canvas");
        let gl;
        try {
            gl = canvas.getContext("webgl");
        } catch(e) {
            try {
                gl = canvas.getContext("experimental-webgl");
            } catch(e) {
                gl = null;
            }
        }
        return gl;
    })();
    beforeEach(function() {
        if (!webgl) {
            this.skip();
        }
    });
    describe("Namespace injection", function() {
        describe("Should be able to access vglCameras", function() {
            it("When the component is the root namespace.", function() {
                const vm = new Vue(VglRenderer);
                assert.isObject(vm.vglCameras);
            });
            it("When the component is a descendant of the other namespace.", function() {
                const vm = new Vue({
                    template: `<vgl-namespace><vgl-renderer ref="renderer" /></vgl-namespace>`,
                    components: {
                        VglNamespace,
                        VglRenderer
                    }
                }).$mount();
                assert.isObject(vm.$refs.renderer.vglCameras);
            });
        });
        describe("Should be able to access vglScenes", function() {
            it("When the component is the root namespace.", function() {
                const vm = new Vue(VglRenderer);
                assert.isObject(vm.vglScenes);
            });
            it("When the component is a descendant of the other namespace.", function() {
                const vm = new Vue({
                    template: `<vgl-namespace><vgl-renderer ref="renderer" /></vgl-namespace>`,
                    components: {
                        VglNamespace,
                        VglRenderer
                    }
                }).$mount();
                assert.isObject(vm.$refs.renderer.vglScenes);
            });
        });
    });
    describe("Creating a renderer", function() {
        describe("Output canvas", function() {
            it("The domElement property of WebGLRenderer instance should be the Vue created canvas.", function() {
                const vm = new Vue(VglRenderer).$mount();
                assert.strictEqual(vm.$refs.rdr, vm.inst.domElement);
            });
        });
        describe("Context attributes", function() {
            describe("The alpha property should affect the alpha attribute.", function() {
                it("When the property is undefined (or false).", function() {
                    const vm = new Vue(VglRenderer).$mount();
                    assert.isFalse(vm.inst.getContextAttributes().alpha);
                });
                it("When the property is true.", function() {
                    const vm = new (Vue.extend(VglRenderer))({propsData: {alpha: true}}).$mount();
                    assert.isTrue(vm.inst.getContextAttributes().alpha);
                });
            });
            describe("The disableDepth property should affect the depth attribute.", function() {
                it("When the property is undefined (or false).", function() {
                    const vm = new Vue(VglRenderer).$mount();
                    assert.isTrue(vm.inst.getContextAttributes().depth);
                });
                it("When the property is true.", function() {
                    const vm = new (Vue.extend(VglRenderer))({propsData: {disableDepth: true}}).$mount();
                    assert.isFalse(vm.inst.getContextAttributes().depth);
                });
            });
            describe("The disableStencil property should affect the stencil attribute.", function() {
                it("When the property is undefined (or false).", function() {
                    const vm = new Vue(VglRenderer).$mount();
                    assert.isTrue(vm.inst.getContextAttributes().stencil);
                });
                it("When the property is true.", function() {
                    const vm = new (Vue.extend(VglRenderer))({propsData: {disableStencil: true}}).$mount();
                    assert.isFalse(vm.inst.getContextAttributes().stencil);
                });
            });
            describe("The antialias property should affect the antialias attribute.", function() {
                it("When the property is undefined (or false).", function() {
                    const vm = new Vue(VglRenderer).$mount();
                    assert.isFalse(vm.inst.getContextAttributes().antialias);
                });
                it("When the property is true.", function() {
                    const vm = new (Vue.extend(VglRenderer))({propsData: {antialias: true}}).$mount();
                    assert.isTrue(vm.inst.getContextAttributes().antialias);
                });
            });
            describe("The disablePremultipliedAlpha property should affect the premultipliedAlpha attribute.", function() {
                it("When the property is undefined (or false).", function() {
                    const vm = new Vue(VglRenderer).$mount();
                    assert.isTrue(vm.inst.getContextAttributes().premultipliedAlpha);
                });
                it("When the property is true.", function() {
                    const vm = new (Vue.extend(VglRenderer))({propsData: {disablePremultipliedAlpha: true}}).$mount();
                    assert.isFalse(vm.inst.getContextAttributes().premultipliedAlpha);
                });
            });
            describe("The preserveDrawingBuffer property should affect the preserveDrawingBuffer attribute.", function() {
                it("When the property is undefined (or false).", function() {
                    const vm = new Vue(VglRenderer).$mount();
                    assert.isFalse(vm.inst.getContextAttributes().preserveDrawingBuffer);
                });
                it("When the property is true.", function() {
                    const vm = new (Vue.extend(VglRenderer))({propsData: {preserveDrawingBuffer: true}}).$mount();
                    assert.isTrue(vm.inst.getContextAttributes().preserveDrawingBuffer);
                });
            });
        });
        describe("Capabilities", function() {
            describe("The logarithmicDepthBuffer property should affect the logarithmicDepthBuffer capability.", function() {
                it("When the property is undefined (or false).", function() {
                    const vm = new Vue(VglRenderer).$mount();
                    assert.isFalse(vm.inst.capabilities.logarithmicDepthBuffer);
                });
                it("When the property is true.", function() {
                    const vm = new (Vue.extend(VglRenderer))({propsData: {logarithmicDepthBuffer: true}}).$mount();
                    assert.isTrue(vm.inst.capabilities.logarithmicDepthBuffer);
                });
            });
            describe("The precision property should affect the precision capability.", function() {
                it("When the property is undefined (or false).", function() {
                    const vm = new Vue(VglRenderer).$mount();
                    assert.strictEqual(vm.inst.capabilities.precision, "highp");
                });
                it("When the property is \"lowp\".", function() {
                    const vm = new (Vue.extend(VglRenderer))({propsData: {precision: "lowp"}}).$mount();
                    assert.strictEqual(vm.inst.capabilities.precision, "lowp");
                });
                it("When the property is \"mediump\".", function() {
                    const vm = new (Vue.extend(VglRenderer))({propsData: {precision: "mediump"}}).$mount();
                    assert.strictEqual(vm.inst.capabilities.precision, "mediump");
                });
                it("When the property is \"highp\".", function() {
                    const vm = new (Vue.extend(VglRenderer))({propsData: {precision: "highp"}}).$mount();
                    assert.strictEqual(vm.inst.capabilities.precision, "highp");
                });
            });
        });
    });
    describe("When any properties are changed", function() {
        describe("Output canvas", function() {
            it("The canvas element should be replaced.", function(done) {
                const vm = new Vue(VglRenderer).$mount();
                const oldCanvas = vm.$refs.rdr;
                vm.alpha = true;
                vm.$nextTick(() => {
                    try {
                        assert.notEqual(oldCanvas, vm.$refs.rdr);
                        done();
                    } catch(e) {
                        done(e);
                    }
                });
            });
            it("The WebGLRenderer instance should be newly created.", function(done) {
                const vm = new Vue(VglRenderer).$mount();
                const oldInst = vm.inst;
                vm.alpha = true;
                vm.$nextTick(() => {
                    try {
                        assert.notEqual(oldInst, vm.inst);
                        done();
                    } catch(e) {
                        done(e);
                    }
                });
            });
            it("The domElement property of WebGLRenderer instance should be the replaced canvas.", function(done) {
                const vm = new Vue(VglRenderer).$mount();
                vm.alpha = true;
                vm.$nextTick(() => {
                    try {
                        assert.strictEqual(vm.inst.domElement, vm.$refs.rdr);
                        done();
                    } catch(e) {
                        done(e);
                    }
                });
            });
        });
    });
});
<commit_msg>Modify the webgl detecting function.<commit_after>describe("VglRenderer component", function() {
    const {VglRenderer, VglNamespace} = VueGL;
    const assert = chai.assert;
    const webgl = (() => {
        const canvas = document.createElement("canvas");
        let gl = null;
        try {
            gl = canvas.getContext("webgl");
        } catch(e) {
            gl = null;
            try {
                gl = canvas.getContext("experimental-webgl");
            } catch(e) {
                gl = null;
            }
        }
        return gl;
    })();
    beforeEach(function() {
        if (!webgl) {
            this.skip();
        }
    });
    describe("Namespace injection", function() {
        describe("Should be able to access vglCameras", function() {
            it("When the component is the root namespace.", function() {
                const vm = new Vue(VglRenderer);
                assert.isObject(vm.vglCameras);
            });
            it("When the component is a descendant of the other namespace.", function() {
                const vm = new Vue({
                    template: `<vgl-namespace><vgl-renderer ref="renderer" /></vgl-namespace>`,
                    components: {
                        VglNamespace,
                        VglRenderer
                    }
                }).$mount();
                assert.isObject(vm.$refs.renderer.vglCameras);
            });
        });
        describe("Should be able to access vglScenes", function() {
            it("When the component is the root namespace.", function() {
                const vm = new Vue(VglRenderer);
                assert.isObject(vm.vglScenes);
            });
            it("When the component is a descendant of the other namespace.", function() {
                const vm = new Vue({
                    template: `<vgl-namespace><vgl-renderer ref="renderer" /></vgl-namespace>`,
                    components: {
                        VglNamespace,
                        VglRenderer
                    }
                }).$mount();
                assert.isObject(vm.$refs.renderer.vglScenes);
            });
        });
    });
    describe("Creating a renderer", function() {
        describe("Output canvas", function() {
            it("The domElement property of WebGLRenderer instance should be the Vue created canvas.", function() {
                const vm = new Vue(VglRenderer).$mount();
                assert.strictEqual(vm.$refs.rdr, vm.inst.domElement);
            });
        });
        describe("Context attributes", function() {
            describe("The alpha property should affect the alpha attribute.", function() {
                it("When the property is undefined (or false).", function() {
                    const vm = new Vue(VglRenderer).$mount();
                    assert.isFalse(vm.inst.getContextAttributes().alpha);
                });
                it("When the property is true.", function() {
                    const vm = new (Vue.extend(VglRenderer))({propsData: {alpha: true}}).$mount();
                    assert.isTrue(vm.inst.getContextAttributes().alpha);
                });
            });
            describe("The disableDepth property should affect the depth attribute.", function() {
                it("When the property is undefined (or false).", function() {
                    const vm = new Vue(VglRenderer).$mount();
                    assert.isTrue(vm.inst.getContextAttributes().depth);
                });
                it("When the property is true.", function() {
                    const vm = new (Vue.extend(VglRenderer))({propsData: {disableDepth: true}}).$mount();
                    assert.isFalse(vm.inst.getContextAttributes().depth);
                });
            });
            describe("The disableStencil property should affect the stencil attribute.", function() {
                it("When the property is undefined (or false).", function() {
                    const vm = new Vue(VglRenderer).$mount();
                    assert.isTrue(vm.inst.getContextAttributes().stencil);
                });
                it("When the property is true.", function() {
                    const vm = new (Vue.extend(VglRenderer))({propsData: {disableStencil: true}}).$mount();
                    assert.isFalse(vm.inst.getContextAttributes().stencil);
                });
            });
            describe("The antialias property should affect the antialias attribute.", function() {
                it("When the property is undefined (or false).", function() {
                    const vm = new Vue(VglRenderer).$mount();
                    assert.isFalse(vm.inst.getContextAttributes().antialias);
                });
                it("When the property is true.", function() {
                    const vm = new (Vue.extend(VglRenderer))({propsData: {antialias: true}}).$mount();
                    assert.isTrue(vm.inst.getContextAttributes().antialias);
                });
            });
            describe("The disablePremultipliedAlpha property should affect the premultipliedAlpha attribute.", function() {
                it("When the property is undefined (or false).", function() {
                    const vm = new Vue(VglRenderer).$mount();
                    assert.isTrue(vm.inst.getContextAttributes().premultipliedAlpha);
                });
                it("When the property is true.", function() {
                    const vm = new (Vue.extend(VglRenderer))({propsData: {disablePremultipliedAlpha: true}}).$mount();
                    assert.isFalse(vm.inst.getContextAttributes().premultipliedAlpha);
                });
            });
            describe("The preserveDrawingBuffer property should affect the preserveDrawingBuffer attribute.", function() {
                it("When the property is undefined (or false).", function() {
                    const vm = new Vue(VglRenderer).$mount();
                    assert.isFalse(vm.inst.getContextAttributes().preserveDrawingBuffer);
                });
                it("When the property is true.", function() {
                    const vm = new (Vue.extend(VglRenderer))({propsData: {preserveDrawingBuffer: true}}).$mount();
                    assert.isTrue(vm.inst.getContextAttributes().preserveDrawingBuffer);
                });
            });
        });
        describe("Capabilities", function() {
            describe("The logarithmicDepthBuffer property should affect the logarithmicDepthBuffer capability.", function() {
                it("When the property is undefined (or false).", function() {
                    const vm = new Vue(VglRenderer).$mount();
                    assert.isFalse(vm.inst.capabilities.logarithmicDepthBuffer);
                });
                it("When the property is true.", function() {
                    const vm = new (Vue.extend(VglRenderer))({propsData: {logarithmicDepthBuffer: true}}).$mount();
                    assert.isTrue(vm.inst.capabilities.logarithmicDepthBuffer);
                });
            });
            describe("The precision property should affect the precision capability.", function() {
                it("When the property is undefined (or false).", function() {
                    const vm = new Vue(VglRenderer).$mount();
                    assert.strictEqual(vm.inst.capabilities.precision, "highp");
                });
                it("When the property is \"lowp\".", function() {
                    const vm = new (Vue.extend(VglRenderer))({propsData: {precision: "lowp"}}).$mount();
                    assert.strictEqual(vm.inst.capabilities.precision, "lowp");
                });
                it("When the property is \"mediump\".", function() {
                    const vm = new (Vue.extend(VglRenderer))({propsData: {precision: "mediump"}}).$mount();
                    assert.strictEqual(vm.inst.capabilities.precision, "mediump");
                });
                it("When the property is \"highp\".", function() {
                    const vm = new (Vue.extend(VglRenderer))({propsData: {precision: "highp"}}).$mount();
                    assert.strictEqual(vm.inst.capabilities.precision, "highp");
                });
            });
        });
    });
    describe("When any properties are changed", function() {
        describe("Output canvas", function() {
            it("The canvas element should be replaced.", function(done) {
                const vm = new Vue(VglRenderer).$mount();
                const oldCanvas = vm.$refs.rdr;
                vm.alpha = true;
                vm.$nextTick(() => {
                    try {
                        assert.notEqual(oldCanvas, vm.$refs.rdr);
                        done();
                    } catch(e) {
                        done(e);
                    }
                });
            });
            it("The WebGLRenderer instance should be newly created.", function(done) {
                const vm = new Vue(VglRenderer).$mount();
                const oldInst = vm.inst;
                vm.alpha = true;
                vm.$nextTick(() => {
                    try {
                        assert.notEqual(oldInst, vm.inst);
                        done();
                    } catch(e) {
                        done(e);
                    }
                });
            });
            it("The domElement property of WebGLRenderer instance should be the replaced canvas.", function(done) {
                const vm = new Vue(VglRenderer).$mount();
                vm.alpha = true;
                vm.$nextTick(() => {
                    try {
                        assert.strictEqual(vm.inst.domElement, vm.$refs.rdr);
                        done();
                    } catch(e) {
                        done(e);
                    }
                });
            });
        });
    });
});
<|endoftext|>


<commit_before>var OneFingerTouch = (function(){
    var hasTouch = 'ontouchstart' in window,
        startEvent = hasTouch ? 'touchstart' : 'mousedown',
        moveEvent = hasTouch ? 'touchmove' : 'mousemove',
        endEvent = hasTouch ? 'touchend' : 'mouseup',
        cancelEvent = hasTouch ? 'touchcancel' : 'mouseup',
        pageX = hasTouch ? 'pageX' : 'clientX',
        pageY = hasTouch ? 'pageY' : 'clientY',
		options = {
			touching: false
		},

        OneFingerTouch = function(el, options){
            this.context = typeof el == 'string' ? document.querySelector(el) : el;
            this.options = {
                preventDefault: true,
                stopPropagation: true,
                minMove: 30, // Pixels
                delayFilter: 500, // Milliseconds
                tapDuration: 50,
                calcSpeed: false,
                calcDistance: false,
                enableHistory: false
            };

            // User defined options
            for (i in options) this.options[i] = options[i];

            this.context.addEventListener(startEvent, this, false);
        };

    OneFingerTouch.prototype = {
        touch: {
            identifier: null, // Unique ID of the Touch object
            startTime: null, // Milliseconds elapsed since 1 January 1970 00:00:00 UTC.
            delay: 0, // Milliseconds
            duration: 0,
            startX: 0, // Pixels
            startY: 0,
            pageX: 0,
            pageY: 0,
            deltaX: 0,
            deltaY: 0,
            distance: 0,
            totalDistance: 0,
            speed: 0, // Pixels per second
            direction: 'tap' // tap, up, down, left, right, upleft, upright, downleft, downright
        },
        stored: {
            // identifier: null,
            // time: null,
            // oldTime: null,
            // startX: 0,
            // startY: 0,
            // deltaX: 0,
            // deltaY: 0,
            // deltaMaxX: 0,
            // deltaMaxY: 0,
            // distanceX: 0,
            // distanceY: 0,
            // distance: 0,
            // oldPageX: 0,
            // oldPageY: 0
        },
        history: [],

        // Work the internal touch object
        _startTouch: function(touch){
            this._resetStored();

            this.touch = {
				identifier: touch.identifier,
                startTime: this.stored.time,
                delay: this.stored.delay,
                ignore: null,
                startX: touch[pageX],
                startY: touch[pageY],
                pageX: touch[pageX],
                pageY: touch[pageY],
                deltaX: 0,
                deltaY: 0,
                duration: 0,
                distance: 0,
                totalDistance: 0,
                speed: 0,
                direction: 'tap'
            }

            if (this.stored.delay > this.options.delayFilter){
                this._resetDirection('withoutEvent');

                options.touching = true;
            } else {
                this.touch.ignore = 'delay';
            }
        },

        _moveTouch: function(touch){
            this._store(touch);

            this.touch.pageX = touch[pageX];
            this.touch.pageY = touch[pageY];
            this.touch.deltaX = this.touch.pageX - this.touch.startX;
            this.touch.deltaY = this.touch.pageY - this.touch.startY;
            this.touch.duration = Date.now() - this.touch.startTime;
            if (this.options.calcSpeed || this.options.calcDistance){
                this.touch.distance = parseInt(Math.sqrt((this.touch.deltaX * this.touch.deltaX) + (this.touch.deltaY * this.touch.deltaY)), 10);
                this.touch.totalDistance += this.stored.distance;
                this.touch.speed = parseInt((this.touch.totalDistance / this.touch.duration * 1000), 10);
            }
            if (this.touch.direction == 'tap') this.touch.direction = null;

            this._changeDirection(this._getDirection());

            if (this.touch.direction){
                if (!this.stored.deltaMaxX || (this.stored.deltaX < 0 && this.stored.deltaX < this.stored.deltaMaxX) || (this.stored.deltaX > 0 && this.stored.deltaX > this.stored.deltaMaxX)){
                    this.stored.deltaMaxX = this.stored.deltaX;
                } else if ((Math.abs(this.stored.deltaMaxX) - Math.abs(this.stored.deltaX)) > this.options.minMove) {
                    this._resetDirection();
                }

                if (!this.stored.deltaMaxY || (this.stored.deltaY < 0 && this.stored.deltaY < this.stored.deltaMaxY) || (this.stored.deltaY > 0 && this.stored.deltaY > this.stored.deltaMaxY)){
                    this.stored.deltaMaxY = this.stored.deltaY;
                } else if ((Math.abs(this.stored.deltaMaxY) - Math.abs(this.stored.deltaY)) > this.options.minMove) {
                    this._resetDirection();
                }
            }
        },

        _endTouch: function(touch){
            this.stored.oldTime = Date.now();
            this.stored.finger = null;

            this.touch.duration = Date.now() - this.touch.startTime;

            if (this.touch.direction == 'tap' && this.touch.duration < this.options.tapDuration){
				this.touch.direction = null;
				this.touch.ignore = 'tapDuration';
			}

			options.touching = false;
        },

        // Store touch values between touches
        _store: function(touch){
            this.stored.deltaX = touch[pageX] - this.stored.startX;
            this.stored.deltaY = touch[pageY] - this.stored.startY;
            if (this.options.calcSpeed || this.options.calcDistance){
                this.stored.distanceX =  touch[pageX] - (this.stored.oldPageX || 0);
                this.stored.distanceY =  touch[pageY] - (this.stored.oldPageY || 0);
                this.stored.distance = parseInt(Math.sqrt((this.stored.distanceX * this.stored.distanceX) + (this.stored.distanceY * this.stored.distanceY)), 10);
            }
            this.stored.oldPageX = touch[pageX];
            this.stored.oldPageY = touch[pageY];

            // deltaMaxX, deltaMaxY are stored by _moveTouch()
            // startX, startY are stored by _resetDirection()
        },

        _resetStored: function(){
            this.stored.time = Date.now();
            this.stored.delay = this.stored.time - (this.stored.oldTime || 0);

            this.stored.startX = this.stored.startY = this.stored.deltaX =
            this.stored.deltaY = this.stored.deltaMaxX = this.stored.deltaMaxY =
            this.stored.distanceX = this.stored.distanceY = this.stored.distance =
            this.stored.oldPageX = this.stored.oldPageY = 0;

            // deltaMaxX, deltaMaxY are also reset by _resetDirection()
        },

        // Handle events
        handleEvent: function(event){
            switch (event.type){
                case startEvent:
					console.log('start');
                    this._start(event);
                    break;
                case moveEvent:
					console.log('move');
                    this._move(event);
                    break;
                case cancelEvent:
					console.log('cancel');
                    this._cancel(event);
                    break;
                case endEvent:
                    console.log('end');
					this._end(event);
                    break;
            }
        },

        _start: function(event){
			// Ignore if we are already tracking a finger
            if (options.touching) return this._ignoreTouch(event);

            if (this.options.stopPropagation) event.stopPropagation();

            this._startTouch(hasTouch ? event.touches[0] : event);

            if (!this.touch.ignore){
                this.context.addEventListener(moveEvent, this, false);
                this.context.addEventListener(endEvent, this, false);
                this.context.addEventListener(cancelEvent, this, false);
            }

            this._fireEvent(this.touch.ignore || 'start');
        },

        _move: function(event){
			// Ignore if more than one finger is touching
			if (hasTouch && event.touches.length > 1) return this._ignoreTouch(event);

            if (this.options.preventDefault) event.preventDefault();
            if (this.options.stopPropagation) event.stopPropagation();

            this._moveTouch(hasTouch ? event.touches[0] : event);

            this._fireEvent('move');
        },

        _cancel: function(event){
            // Forward
            this._end(event);
        },

        _end: function(event){
			// If it's not the last finger ending the touch,
			// forward to _move() to find out where the first one has gone
			if (hasTouch && event.touches.length) return this._move(event);

            if (this.options.stopPropagation) event.stopPropagation();

            this.context.removeEventListener(moveEvent, this, false);
            this.context.removeEventListener(endEvent, this, false);
            this.context.removeEventListener(cancelEvent, this, false);

            this._endTouch();

            this._fireEvent('end');
        },

        _ignoreTouch: function(event){
            if (this.options.preventDefault) event.preventDefault();
            if (this.options.stopPropagation) event.stopPropagation();

            this._fireEvent('ignore');
        },

        _fireEvent: function(type){
            var event = document.createEvent("Event");
            event.initEvent('onefingertouch-' + type, true, true);
            event.onefingertouch = this.touch;

            // consider one event for all types:
            //
            // event.initEvent('onefingertouch', true, true);
            // event.onefingertouch = {type: type, touch: this.touch};

            // enable history, could go here ? e.g.:
            //
            // history.push(event.onefingertouch);

			console.log('__' + type);
            this.context.dispatchEvent(event);
        },

        // Where's the finger going
        _getDirection: function(){
            var foundDirection = false;

            if (Math.abs(this.stored.deltaX) > this.options.minMove || Math.abs(this.stored.deltaY) > this.options.minMove){
                var triangle = {
                    side: {
                        a: Math.abs(this.stored.deltaY),
                        b: Math.abs(this.stored.deltaX),
                        c: null
                    },
                    angle: {
                        A: null,
                        B: null,
                        C: null
                    }
                };

                triangle.side.c = Math.sqrt((triangle.side.a * triangle.side.a) + (triangle.side.b * triangle.side.b));

                var above = (triangle.side.b * triangle.side.b) + (triangle.side.c * triangle.side.c) - (triangle.side.a * triangle.side.a);
                var below = 2 * triangle.side.b * triangle.side.c;

                triangle.angle.A = ((180/Math.PI) * Math.acos(above/below)) || 90;

                for (var direction in this.directions){
                    if (!foundDirection && this.directions[direction](this.stored.deltaX, this.stored.deltaY, triangle.angle.A)) foundDirection = direction;
                }
            }

            return foundDirection;
        },

        _changeDirection: function(direction){
            if (direction && direction != this.touch.direction){
                this.touch.direction = direction;

                this._fireEvent('directionChange');
            }
        },

        _resetDirection: function(withoutEvent){
            if (this.touch.direction != 'tap') this.touch.direction = null;

            this.stored.deltaMaxX = this.stored.deltaMaxY = 0;
            this.stored.startX = this.touch.pageX;
            this.stored.startY = this.touch.pageY;

            if (!withoutEvent) this._fireEvent('resetDirection');
        },

        directions: {
            // X pixels, Y pixels, A degrees

            'up': function(X, Y, A){
                return Y < 0 && A > 60;
            },

            'down': function(X, Y, A){
                return Y > 0 && A > 60;
            },

            'left': function(X, Y, A){
                return X < 0 && A < 30;
            },

            'right': function(X, Y, A){
                return X > 0 && A < 30;
            },

            'upleft': function(X, Y, A){
                return Y < 0 && X < 0 && A >= 30 && A <= 60;
            },

            'upright': function(X, Y, A){
                return Y < 0 && X > 0 && A >= 30 && A <= 60;
            },

            'downleft': function(X, Y, A){
                return Y > 0 && X < 0 && A >= 30 && A <= 60;
            },

            'downright': function(X, Y, A){
                return Y > 0 && X > 0 && A >= 30 && A <= 60;
            }

        }
    };

    return OneFingerTouch;
})();<commit_msg>tabs ...<commit_after>var OneFingerTouch = (function(){
    var hasTouch = 'ontouchstart' in window,
        startEvent = hasTouch ? 'touchstart' : 'mousedown',
        moveEvent = hasTouch ? 'touchmove' : 'mousemove',
        endEvent = hasTouch ? 'touchend' : 'mouseup',
        cancelEvent = hasTouch ? 'touchcancel' : 'mouseup',
        pageX = hasTouch ? 'pageX' : 'clientX',
        pageY = hasTouch ? 'pageY' : 'clientY',
        options = {
            touching: false
        },

        OneFingerTouch = function(el, options){
            this.context = typeof el == 'string' ? document.querySelector(el) : el;
            this.options = {
                preventDefault: true,
                stopPropagation: true,
                minMove: 30, // Pixels
                delayFilter: 500, // Milliseconds
                tapDuration: 50,
                calcSpeed: false,
                calcDistance: false,
                enableHistory: false
            };

            // User defined options
            for (i in options) this.options[i] = options[i];

            this.context.addEventListener(startEvent, this, false);
        };

    OneFingerTouch.prototype = {
        touch: {
            identifier: null, // Unique ID of the Touch object
            startTime: null, // Milliseconds elapsed since 1 January 1970 00:00:00 UTC.
            delay: 0, // Milliseconds
            duration: 0,
            startX: 0, // Pixels
            startY: 0,
            pageX: 0,
            pageY: 0,
            deltaX: 0,
            deltaY: 0,
            distance: 0,
            totalDistance: 0,
            speed: 0, // Pixels per second
            direction: 'tap' // tap, up, down, left, right, upleft, upright, downleft, downright
        },
        stored: {
            // identifier: null,
            // time: null,
            // oldTime: null,
            // startX: 0,
            // startY: 0,
            // deltaX: 0,
            // deltaY: 0,
            // deltaMaxX: 0,
            // deltaMaxY: 0,
            // distanceX: 0,
            // distanceY: 0,
            // distance: 0,
            // oldPageX: 0,
            // oldPageY: 0
        },
        history: [],

        // Work the internal touch object
        _startTouch: function(touch){
            this._resetStored();

            this.touch = {
                identifier: touch.identifier,
                startTime: this.stored.time,
                delay: this.stored.delay,
                ignore: null,
                startX: touch[pageX],
                startY: touch[pageY],
                pageX: touch[pageX],
                pageY: touch[pageY],
                deltaX: 0,
                deltaY: 0,
                duration: 0,
                distance: 0,
                totalDistance: 0,
                speed: 0,
                direction: 'tap'
            }

            if (this.stored.delay > this.options.delayFilter){
                this._resetDirection('withoutEvent');

                options.touching = true;
            } else {
                this.touch.ignore = 'delay';
            }
        },

        _moveTouch: function(touch){
            this._store(touch);

            this.touch.pageX = touch[pageX];
            this.touch.pageY = touch[pageY];
            this.touch.deltaX = this.touch.pageX - this.touch.startX;
            this.touch.deltaY = this.touch.pageY - this.touch.startY;
            this.touch.duration = Date.now() - this.touch.startTime;
            if (this.options.calcSpeed || this.options.calcDistance){
                this.touch.distance = parseInt(Math.sqrt((this.touch.deltaX * this.touch.deltaX) + (this.touch.deltaY * this.touch.deltaY)), 10);
                this.touch.totalDistance += this.stored.distance;
                this.touch.speed = parseInt((this.touch.totalDistance / this.touch.duration * 1000), 10);
            }
            if (this.touch.direction == 'tap') this.touch.direction = null;

            this._changeDirection(this._getDirection());

            if (this.touch.direction){
                if (!this.stored.deltaMaxX || (this.stored.deltaX < 0 && this.stored.deltaX < this.stored.deltaMaxX) || (this.stored.deltaX > 0 && this.stored.deltaX > this.stored.deltaMaxX)){
                    this.stored.deltaMaxX = this.stored.deltaX;
                } else if ((Math.abs(this.stored.deltaMaxX) - Math.abs(this.stored.deltaX)) > this.options.minMove) {
                    this._resetDirection();
                }

                if (!this.stored.deltaMaxY || (this.stored.deltaY < 0 && this.stored.deltaY < this.stored.deltaMaxY) || (this.stored.deltaY > 0 && this.stored.deltaY > this.stored.deltaMaxY)){
                    this.stored.deltaMaxY = this.stored.deltaY;
                } else if ((Math.abs(this.stored.deltaMaxY) - Math.abs(this.stored.deltaY)) > this.options.minMove) {
                    this._resetDirection();
                }
            }
        },

        _endTouch: function(touch){
            this.stored.oldTime = Date.now();
            this.stored.finger = null;

            this.touch.duration = Date.now() - this.touch.startTime;

            if (this.touch.direction == 'tap' && this.touch.duration < this.options.tapDuration){
                this.touch.direction = null;
                this.touch.ignore = 'tapDuration';
            }

            options.touching = false;
        },

        // Store touch values between touches
        _store: function(touch){
            this.stored.deltaX = touch[pageX] - this.stored.startX;
            this.stored.deltaY = touch[pageY] - this.stored.startY;
            if (this.options.calcSpeed || this.options.calcDistance){
                this.stored.distanceX =  touch[pageX] - (this.stored.oldPageX || 0);
                this.stored.distanceY =  touch[pageY] - (this.stored.oldPageY || 0);
                this.stored.distance = parseInt(Math.sqrt((this.stored.distanceX * this.stored.distanceX) + (this.stored.distanceY * this.stored.distanceY)), 10);
            }
            this.stored.oldPageX = touch[pageX];
            this.stored.oldPageY = touch[pageY];

            // deltaMaxX, deltaMaxY are stored by _moveTouch()
            // startX, startY are stored by _resetDirection()
        },

        _resetStored: function(){
            this.stored.time = Date.now();
            this.stored.delay = this.stored.time - (this.stored.oldTime || 0);

            this.stored.startX = this.stored.startY = this.stored.deltaX =
            this.stored.deltaY = this.stored.deltaMaxX = this.stored.deltaMaxY =
            this.stored.distanceX = this.stored.distanceY = this.stored.distance =
            this.stored.oldPageX = this.stored.oldPageY = 0;

            // deltaMaxX, deltaMaxY are also reset by _resetDirection()
        },

        // Handle events
        handleEvent: function(event){
            switch (event.type){
                case startEvent:
                    console.log('start');
                    this._start(event);
                    break;
                case moveEvent:
                    console.log('move');
                    this._move(event);
                    break;
                case cancelEvent:
                    console.log('cancel');
                    this._cancel(event);
                    break;
                case endEvent:
                    console.log('end');
                    this._end(event);
                    break;
            }
        },

        _start: function(event){
            // Ignore if we are already tracking a finger
            if (options.touching) return this._ignoreTouch(event);

            if (this.options.stopPropagation) event.stopPropagation();

            this._startTouch(hasTouch ? event.touches[0] : event);

            if (!this.touch.ignore){
                this.context.addEventListener(moveEvent, this, false);
                this.context.addEventListener(endEvent, this, false);
                this.context.addEventListener(cancelEvent, this, false);
            }

            this._fireEvent(this.touch.ignore || 'start');
        },

        _move: function(event){
            // Ignore if more than one finger is touching
            if (hasTouch && event.touches.length > 1) return this._ignoreTouch(event);

            if (this.options.preventDefault) event.preventDefault();
            if (this.options.stopPropagation) event.stopPropagation();

            this._moveTouch(hasTouch ? event.touches[0] : event);

            this._fireEvent('move');
        },

        _cancel: function(event){
            // Forward
            this._end(event);
        },

        _end: function(event){
            // If it's not the last finger ending the touch,
            // forward to _move() to find out where the first one has gone
            if (hasTouch && event.touches.length) return this._move(event);

            if (this.options.stopPropagation) event.stopPropagation();

            this.context.removeEventListener(moveEvent, this, false);
            this.context.removeEventListener(endEvent, this, false);
            this.context.removeEventListener(cancelEvent, this, false);

            this._endTouch();

            this._fireEvent('end');
        },

        _ignoreTouch: function(event){
            if (this.options.preventDefault) event.preventDefault();
            if (this.options.stopPropagation) event.stopPropagation();

            this._fireEvent('ignore');
        },

        _fireEvent: function(type){
            var event = document.createEvent("Event");
            event.initEvent('onefingertouch-' + type, true, true);
            event.onefingertouch = this.touch;

            // consider one event for all types:
            //
            // event.initEvent('onefingertouch', true, true);
            // event.onefingertouch = {type: type, touch: this.touch};

            // enable history, could go here ? e.g.:
            //
            // history.push(event.onefingertouch);

            console.log('__' + type);
            this.context.dispatchEvent(event);
        },

        // Where's the finger going
        _getDirection: function(){
            var foundDirection = false;

            if (Math.abs(this.stored.deltaX) > this.options.minMove || Math.abs(this.stored.deltaY) > this.options.minMove){
                var triangle = {
                    side: {
                        a: Math.abs(this.stored.deltaY),
                        b: Math.abs(this.stored.deltaX),
                        c: null
                    },
                    angle: {
                        A: null,
                        B: null,
                        C: null
                    }
                };

                triangle.side.c = Math.sqrt((triangle.side.a * triangle.side.a) + (triangle.side.b * triangle.side.b));

                var above = (triangle.side.b * triangle.side.b) + (triangle.side.c * triangle.side.c) - (triangle.side.a * triangle.side.a);
                var below = 2 * triangle.side.b * triangle.side.c;

                triangle.angle.A = ((180/Math.PI) * Math.acos(above/below)) || 90;

                for (var direction in this.directions){
                    if (!foundDirection && this.directions[direction](this.stored.deltaX, this.stored.deltaY, triangle.angle.A)) foundDirection = direction;
                }
            }

            return foundDirection;
        },

        _changeDirection: function(direction){
            if (direction && direction != this.touch.direction){
                this.touch.direction = direction;

                this._fireEvent('directionChange');
            }
        },

        _resetDirection: function(withoutEvent){
            if (this.touch.direction != 'tap') this.touch.direction = null;

            this.stored.deltaMaxX = this.stored.deltaMaxY = 0;
            this.stored.startX = this.touch.pageX;
            this.stored.startY = this.touch.pageY;

            if (!withoutEvent) this._fireEvent('resetDirection');
        },

        directions: {
            // X pixels, Y pixels, A degrees

            'up': function(X, Y, A){
                return Y < 0 && A > 60;
            },

            'down': function(X, Y, A){
                return Y > 0 && A > 60;
            },

            'left': function(X, Y, A){
                return X < 0 && A < 30;
            },

            'right': function(X, Y, A){
                return X > 0 && A < 30;
            },

            'upleft': function(X, Y, A){
                return Y < 0 && X < 0 && A >= 30 && A <= 60;
            },

            'upright': function(X, Y, A){
                return Y < 0 && X > 0 && A >= 30 && A <= 60;
            },

            'downleft': function(X, Y, A){
                return Y > 0 && X < 0 && A >= 30 && A <= 60;
            },

            'downright': function(X, Y, A){
                return Y > 0 && X > 0 && A >= 30 && A <= 60;
            }

        }
    };

    return OneFingerTouch;
})();<|endoftext|>