<commit_before>/* jslint asi:true, browser:true */

if (typeof Lexis == "undefined") var Lexis = {};

var Dictionary = {
    description: null,
    forms: {},
    getHTML: function(e) {
        var i = 0;
        var s = "";
        var current_node = null;
        for (i = 0; i < e.childNodes.length; i++) {
            current_node = e.childNodes.item(i);
            if (current_node.nodeType === 3) {
                s += current_node.textContent;
            }
            else if (current_node.nodeType === 1) {
                switch (current_node.tagName) {
                    case "wordref":
                        s += "" + current_node.textContent + "";
                        break;
                    case "etymon":
                        if (current_node.hasAttributeNS("http://www.w3.org/XML/1998/namespace", "lang")) s += "" + current_node.textContent + "";
                        else s += "" + current_node.textContent + "";
                        break;
                }
            }
        }
        return s;
    },
    getHumanReadableWordClass: function(word_class) {
        if (!word_class) word_class = "";
        var class_list = word_class.split(" ");
        var class_item_list = null;
        var i = 0;
        var j = 0;
        var s = "";
        var q = null;
        for (i = 0; i < class_list.length; i++) {
            if (i) s += ", ";
            class_item_list = class_list[i].split(".");
            q = {};
            for (j = 0; j < class_item_list.length; j++) {
                q[class_item_list[j]] = true;
            }

            if (q.pfv) s += "perfective ";
            if (q.prog) s += "progressive ";
            if (q.cont) s += "continuous ";
            if (q["1"]) s += "first-person ";
            if (q["2"]) s += "second-person ";
            if (q["3"]) s += "third-person ";
            if (q.mod) {
                if (q.mir) s += "mirative ";
                else if (q.opt) s += "optative ";
                else if (q.hort) s += "hortative ";
                else if (q.perm) s += "permissive ";
                else if (q.jus) s += "jussive ";
                else if (q.int) s += "interrogative ";
                else s += "modal ";
            }
            if (q.det) {
                if (q.qnt) s += "quantifier ";
                else if (q.num) s += "numeral ";
                else if (q.dem) s += "demonstrative ";
                else s += "determiner";
            }
            if (q.post) s += "post-position";
            if (q.ptcl) s += "particle ";
            if (q.adj) s += "adjective ";
            if (q.adv) s += "adverb ";
            if (q.pron) s += "pronoun ";
            if (q.n) s += "noun ";
            if (q.v) s += "verb ";
            s.trim();
        }
        return s;
    },
    getLemmaFromId: function(id) {
        return Dictionary.lemmas[id.split(":")[0]][Number(id.split(":")[1])]
    },
    getLemmaName: function(lemma) {
        return lemma.replace(/:/g, "-").replace(/^-+|[0-9]+$/g, "");
    },
    ids: [],
    init: function() {
        var script = document.createElement("script");
        script.type = "text/javascript";
        script.addEventListener("load", function() {Dictionary.load(document.documentElement.dataset.src + "?" + new Date().getTime())}, false);
        document.head.appendChild(script);
        script.src = "http://leaf.faint.xyz/langdev/!DATA!/master/!DATA!/LexisML/scripts/normalize.js";
    },
    lang: "",
    lemmas: {},
    lexis: undefined,
    load: function(src) {
        Dictionary.Requester.addEventListener("load", Dictionary.setup, false);
        Dictionary.Requester.open("get", src, true);
        Dictionary.Requester.overrideMimeType("text/xml");
        Dictionary.Requester.send();
    },
    Requester: new XMLHttpRequest(),
    setup: function() {
        Dictionary.lang = document.documentElement.lang;
        Dictionary.lexis = Dictionary.Requester.responseXML;
        Lexis.normalize(Dictionary.lexis);
        var i = 0;
        var j = 0;
        var elements = Dictionary.lexis.documentElement.childNodes;
        var current_element;
        var current_lemma;
        var lemma_name;
        var lemma_id;
        var article_html;
        var section_html;
        for (i = 0; i < elements.length; i++) {
            if (elements.item(i).nodeType !== 1) continue;
            current_element = elements.item(i);
            switch (current_element.tagName) {
                case "meta":
                    switch (current_element.getAttribute("name")) {
                        case "title":
                            Dictionary.title = [current_element.getAttributeNS("http://www.w3.org/XML/1998/namespace", "lang"), current_element.textContent];
                            break;
                        case "description":
                            Dictionary.description = [current_element.getAttributeNS("http://www.w3.org/XML/1998/namespace", "lang"), current_element.textContent];
                            break;
                        case "splash":
                            Dictionary.splashes[Dictionary.splashes.length] = [current_element.getAttributeNS("http://www.w3.org/XML/1998/namespace", "lang"), current_element.textContent];
                            break;
                    }
                    break;
                case "affix":
                case "word":
                    lemma_name = Dictionary.getLemmaName(current_element.getAttribute("lemma"));
                    if (Dictionary.lemmas[lemma_name] === undefined) Dictionary.lemmas[lemma_name] = [];
                    lemma_id = lemma_name + ":" + Dictionary.lemmas[lemma_name].length;
                    current_lemma = Dictionary.lemmas[lemma_name][Dictionary.lemmas[lemma_name].length] = {
                        type: current_element.tagName,
                        name: current_element.getAttribute("lemma"),
                        id: lemma_id,
                        word_class: null,
                        lang: current_element.getAttributeNS("http://www.w3.org/XML/1998/namespace", "lang"),
                        forms: current_element.getElementsByTagNameNS("http://leaf.faint.xyz/lexisml", "form"),
                        etymology: current_element.getElementsByTagNameNS("http://leaf.faint.xyz/lexisml", "etymology").item(0),
                        meanings: current_element.getElementsByTagNameNS("http://leaf.faint.xyz/lexisml", "meaning")
                    }
                    for (j = 0; j < current_lemma.forms.length; j++) {
                        if (current_lemma.forms.item(j).textContent == current_lemma.name) {
                            current_lemma.word_class = current_lemma.forms.item(j).getAttribute("class");
                            break;
                        }
                    }
                    Dictionary.ids[Dictionary.ids.length] = lemma_id;
                    break;
            }
        }
        Dictionary.ids.sort(function (a, b) {return String(a).localeCompare(String(b));});
        var main_article = document.createElement("article");
        document.title = Dictionary.title[1];
        document.getElementsByTagName("title").item(0).lang = Dictionary.title[0];
        article_html = "
";
        article_html += "
" + Dictionary.title[1] + "
";
        if (Dictionary.splashes.length) {
            i = Math.floor(Math.random()*Dictionary.splashes.length);
            article_html += "
" + Dictionary.splashes[i][1] + "
";
        }
        if (Dictionary.description !== null) article_html += "

" + Dictionary.description[1] + "

";
        article_html += "";
        main_article.innerHTML = article_html;
        for (i = 0; i < Dictionary.ids.length; i++) {
            current_element = document.createElement("section");
            current_lemma = Dictionary.getLemmaFromId(Dictionary.ids[i]);
            current_element.lang = current_lemma.lang;
            current_element.id = Dictionary.ids[i];
            section_html = "";
            section_html += "
<dfn>" + current_lemma.name + "</dfn>
";
            if (current_lemma.type == "word") {
                if (current_lemma.word_class) {
                    section_html += "
" + Dictionary.getHumanReadableWordClass(current_lemma.word_class) + "
";
                }
                section_html += "
";
                for (j = 0; j < current_lemma.forms.length; j++) {
                    if (current_lemma.forms.item(j).textContent != current_lemma.name) section_html += Dictionary.getHumanReadableWordClass(current_lemma.forms.item(j).getAttribute("class")) + " : " + current_lemma.forms.item(j).textContent + "";
                    if (j + 1 != current_lemma.forms.length) section_html += " ";
                }
                section_html += "
"
            }
            else if (current_lemma.type == "affix") {
                section_html += "
affix
";
            }
            section_html += "";
            if (current_lemma.meanings.length > 1) {
                section_html += "
";
                for (j = 0; j < current_lemma.meanings.length; j++) {
                    section_html += "
";
                    if (current_lemma.meanings.item(j).getAttribute("class") != current_lemma.word_class) section_html += "(" + Dictionary.getHumanReadableWordClass(current_lemma.meanings.item(j).getAttribute("class")) + ") ";
                    section_html += Dictionary.getHTML(current_lemma.meanings.item(j));
                    section_html += "
";
                }
                section_html += "
";
            }
            else if (current_lemma.meanings.length == 1) {
                section_html += "
";
                if (current_lemma.meanings.item(0).getAttribute("class") != current_lemma.word_class) section_html += "(" + Dictionary.getHumanReadableWordClass(current_lemma.meanings.item(0).getAttribute("class")) + ") ";
                section_html += Dictionary.getHTML(current_lemma.meanings.item(0));
                section_html += "
";
            }
            if (current_lemma.etymology) section_html += "
etymology

" + Dictionary.getHTML(current_lemma.etymology) + "
";
            current_element.innerHTML = section_html;
            main_article.appendChild(current_element);
        }
        document.body.textContent = null;
        document.body.appendChild(document.createElement("main").appendChild(main_article).parentElement);
    },
    splashes: [],
    title: "",
    title_lang: ""
}

window.addEventListener("load", Dictionary.init, false);
<commit_msg>Filtering added<commit_after>/* jslint asi:true, browser:true */

if (typeof Lexis == "undefined") var Lexis = {};

var Dictionary = {
    description: null,
    element: null,
    filter: function() {
        var i = 0;
        var current_element = null;
        for (i = 0; i < Dictionary.element.childElementCount; i++) {
            current_element = Dictionary.element.children.item(i);
            if (window.location.hash && ((window.location.hash.indexOf(":") === -1 && current_element.id.substring(0,current_element.id.indexOf(":")) === window.location.hash.substr(1)) || current_element.id === window.location.hash.substr(1))) current_element.removeAttribute("hidden");
            else current_element.setAttribute("hidden", "");
        }
    },
    forms: {},
    getHTML: function(e) {
        var i = 0;
        var s = "";
        var current_node = null;
        for (i = 0; i < e.childNodes.length; i++) {
            current_node = e.childNodes.item(i);
            if (current_node.nodeType === 3) {
                s += current_node.textContent;
            }
            else if (current_node.nodeType === 1) {
                switch (current_node.tagName) {
                    case "wordref":
                        s += "" + current_node.textContent + "";
                        break;
                    case "etymon":
                        if (current_node.hasAttributeNS("http://www.w3.org/XML/1998/namespace", "lang")) s += "" + current_node.textContent + "";
                        else s += "" + current_node.textContent + "";
                        break;
                }
            }
        }
        return s;
    },
    getHumanReadableWordClass: function(word_class) {
        if (!word_class) word_class = "";
        var class_list = word_class.split(" ");
        var class_item_list = null;
        var i = 0;
        var j = 0;
        var s = "";
        var q = null;
        for (i = 0; i < class_list.length; i++) {
            if (i) s += ", ";
            class_item_list = class_list[i].split(".");
            q = {};
            for (j = 0; j < class_item_list.length; j++) {
                q[class_item_list[j]] = true;
            }

            if (q.pfv) s += "perfective ";
            if (q.prog) s += "progressive ";
            if (q.cont) s += "continuous ";
            if (q["1"]) s += "first-person ";
            if (q["2"]) s += "second-person ";
            if (q["3"]) s += "third-person ";
            if (q.mod) {
                if (q.mir) s += "mirative ";
                else if (q.opt) s += "optative ";
                else if (q.hort) s += "hortative ";
                else if (q.perm) s += "permissive ";
                else if (q.jus) s += "jussive ";
                else if (q.int) s += "interrogative ";
                else s += "modal ";
            }
            if (q.det) {
                if (q.qnt) s += "quantifier ";
                else if (q.num) s += "numeral ";
                else if (q.dem) s += "demonstrative ";
                else s += "determiner";
            }
            if (q.post) s += "post-position";
            if (q.ptcl) s += "particle ";
            if (q.adj) s += "adjective ";
            if (q.adv) s += "adverb ";
            if (q.pron) s += "pronoun ";
            if (q.n) s += "noun ";
            if (q.v) s += "verb ";
            s.trim();
        }
        return s;
    },
    getLemmaFromId: function(id) {
        return Dictionary.lemmas[id.split(":")[0]][Number(id.split(":")[1])]
    },
    getLemmaName: function(lemma) {
        return lemma.replace(/:/g, "-").replace(/^-+|[0-9]+$/g, "");
    },
    ids: [],
    init: function() {
        var script = document.createElement("script");
        script.type = "text/javascript";
        script.addEventListener("load", function() {Dictionary.load(document.documentElement.dataset.src + "?" + new Date().getTime())}, false);
        document.head.appendChild(script);
        script.src = "http://leaf.faint.xyz/langdev/!DATA!/master/!DATA!/LexisML/scripts/normalize.js";
    },
    lang: "",
    lemmas: {},
    lexis: undefined,
    load: function(src) {
        Dictionary.Requester.addEventListener("load", Dictionary.setup, false);
        Dictionary.Requester.open("get", src, true);
        Dictionary.Requester.overrideMimeType("text/xml");
        Dictionary.Requester.send();
    },
    Requester: new XMLHttpRequest(),
    setup: function() {
        Dictionary.lang = document.documentElement.lang;
        Dictionary.lexis = Dictionary.Requester.responseXML;
        Lexis.normalize(Dictionary.lexis);
        var i = 0;
        var j = 0;
        var elements = Dictionary.lexis.documentElement.childNodes;
        var current_element;
        var current_lemma;
        var lemma_name;
        var lemma_id;
        var article_html;
        var section_html;
        for (i = 0; i < elements.length; i++) {
            if (elements.item(i).nodeType !== 1) continue;
            current_element = elements.item(i);
            switch (current_element.tagName) {
                case "meta":
                    switch (current_element.getAttribute("name")) {
                        case "title":
                            Dictionary.title = [current_element.getAttributeNS("http://www.w3.org/XML/1998/namespace", "lang"), current_element.textContent];
                            break;
                        case "description":
                            Dictionary.description = [current_element.getAttributeNS("http://www.w3.org/XML/1998/namespace", "lang"), current_element.textContent];
                            break;
                        case "splash":
                            Dictionary.splashes[Dictionary.splashes.length] = [current_element.getAttributeNS("http://www.w3.org/XML/1998/namespace", "lang"), current_element.textContent];
                            break;
                    }
                    break;
                case "affix":
                case "word":
                    lemma_name = Dictionary.getLemmaName(current_element.getAttribute("lemma"));
                    if (Dictionary.lemmas[lemma_name] === undefined) Dictionary.lemmas[lemma_name] = [];
                    lemma_id = lemma_name + ":" + Dictionary.lemmas[lemma_name].length;
                    current_lemma = Dictionary.lemmas[lemma_name][Dictionary.lemmas[lemma_name].length] = {
                        type: current_element.tagName,
                        name: current_element.getAttribute("lemma"),
                        id: lemma_id,
                        word_class: null,
                        lang: current_element.getAttributeNS("http://www.w3.org/XML/1998/namespace", "lang"),
                        forms: current_element.getElementsByTagNameNS("http://leaf.faint.xyz/lexisml", "form"),
                        etymology: current_element.getElementsByTagNameNS("http://leaf.faint.xyz/lexisml", "etymology").item(0),
                        meanings: current_element.getElementsByTagNameNS("http://leaf.faint.xyz/lexisml", "meaning")
                    }
                    for (j = 0; j < current_lemma.forms.length; j++) {
                        if (current_lemma.forms.item(j).textContent == current_lemma.name) {
                            current_lemma.word_class = current_lemma.forms.item(j).getAttribute("class");
                            break;
                        }
                    }
                    Dictionary.ids[Dictionary.ids.length] = lemma_id;
                    break;
            }
        }
        Dictionary.ids.sort(function (a, b) {return String(a).localeCompare(String(b));});
        Dictionary.element = document.createElement("article");
        document.title = Dictionary.title[1];
        document.getElementsByTagName("title").item(0).lang = Dictionary.title[0];
        article_html = "
";
        article_html += "
" + Dictionary.title[1] + "
";
        if (Dictionary.splashes.length) {
            i = Math.floor(Math.random()*Dictionary.splashes.length);
            article_html += "
" + Dictionary.splashes[i][1] + "
";
        }
        if (Dictionary.description !== null) article_html += "

" + Dictionary.description[1] + "
";
        article_html += "
filter: <input id='input-filter' type='text' autocomplete='off' autofocus inputmode='latin' placeholder='enter search term…' required spellcheck='false'> <button id='input-button'>ok</button>
";
        article_html += "";
        Dictionary.element.innerHTML = article_html;
        for (i = 0; i < Dictionary.ids.length; i++) {
            current_element = document.createElement("section");
            current_lemma = Dictionary.getLemmaFromId(Dictionary.ids[i]);
            current_element.lang = current_lemma.lang;
            current_element.id = Dictionary.ids[i];
            current_element.setAttribute("hidden", "");
            section_html = "";
            section_html += "
<dfn>" + current_lemma.name + "</dfn>
";
            if (current_lemma.type == "word") {
                if (current_lemma.word_class) {
                    section_html += "
" + Dictionary.getHumanReadableWordClass(current_lemma.word_class) + "
";
                }
                section_html += "
";
                for (j = 0; j < current_lemma.forms.length; j++) {
                    if (current_lemma.forms.item(j).textContent != current_lemma.name) section_html += Dictionary.getHumanReadableWordClass(current_lemma.forms.item(j).getAttribute("class")) + " : " + current_lemma.forms.item(j).textContent + "";
                    if (j + 1 != current_lemma.forms.length) section_html += " ";
                }
                section_html += "
"
            }
            else if (current_lemma.type == "affix") {
                section_html += "
affix
";
            }
            section_html += "";
            if (current_lemma.meanings.length > 1) {
                section_html += "
";
                for (j = 0; j < current_lemma.meanings.length; j++) {
                    section_html += "
";
                    if (current_lemma.meanings.item(j).getAttribute("class") != current_lemma.word_class) section_html += "(" + Dictionary.getHumanReadableWordClass(current_lemma.meanings.item(j).getAttribute("class")) + ") ";
                    section_html += Dictionary.getHTML(current_lemma.meanings.item(j));
                    section_html += "
";
                }
                section_html += "
";
            }
            else if (current_lemma.meanings.length == 1) {
                section_html += "
";
                if (current_lemma.meanings.item(0).getAttribute("class") != current_lemma.word_class) section_html += "(" + Dictionary.getHumanReadableWordClass(current_lemma.meanings.item(0).getAttribute("class")) + ") ";
                section_html += Dictionary.getHTML(current_lemma.meanings.item(0));
                section_html += "
";
            }
            if (current_lemma.etymology) section_html += "
etymology

" + Dictionary.getHTML(current_lemma.etymology) + "
";
            current_element.innerHTML = section_html;
            Dictionary.element.appendChild(current_element);
        }
        document.body.textContent = null;
        document.body.appendChild(document.createElement("main").appendChild(Dictionary.element).parentElement);
        document.getElementById("filter-button").addEventListener("click", function(){window.location.hash = Dictionary.getLemmaName(document.getElementById("filter-input").value);} ,false);
        document.getElementById("filter-input").addEventListener("keypress", function(e){if (e.key === "Enter" || e.keyCode === 13) window.location.hash = Dictionary.getLemmaName(document.getElementById("filter-input").value);} ,false);
        Dictionary.filter();
    },
    splashes: [],
    title: "",
    title_lang: ""
}

window.addEventListener("load", Dictionary.init, false);
window.addEventListener("hashchange", Dictionary.filter, false);
<|endoftext|>


<commit_before>/* jslint asi:true, browser:true */

if (typeof Lexis == "undefined") var Lexis = {};

var Dictionary = {
    forms: {},
    getLemmaFromId: function(id) {
        return Dictionary.lemmas[id.split(":")[0]][Number(id.split(":")[1])]
    },
    ids: [],
    init: function() {
        var script = document.createElement("script");
        script.type = "text/javascript";
        script.addEventListener("load", function() {Dictionary.load(document.documentElement.dataset.src)}, false);
        document.head.appendChild(script);
        script.src = "http://leaf.faint.xyz/langdev/!DATA!/master/!DATA!/LexisML/scripts/normalize.js";
    },
    lang: "",
    lemmas: {},
    lexis: undefined,
    load: function(src) {
        Dictionary.Requester.addEventListener("load", Dictionary.setup, false);
        Dictionary.Requester.open("get", src, true);
        Dictionary.Requester.overrideMimeType("text/xml");
        Dictionary.Requester.send();
    },
    Requester: new XMLHttpRequest(),
    setup: function() {
        Dictionary.lang = document.documentElement.lang;
        Dictionary.lexis = Dictionary.Requester.responseXML;
        Lexis.normalize(Dictionary.lexis);
        var i = 0;
        var j = 0;
        var elements = Dictionary.lexis.documentElement.children;
        var current_element;
        var current_forms;
        var current_meanings;
        var current_lemma;
        var lemma_name;
        var lemma_id;
        var lemma_class;
        var lemma_forms;
        var lemma_meanings;
        var article_html;
        for (i = 0; i < elements.length; i++) {
            current_element = elements.item(i);
            switch (current_element.tagName) {
                case "meta":
                    switch (current_element.getAttributeNS("http://leaf.faint.xyz/lexisml", "name")) {
                        case "title":
                            Dictionary.title = [current_element.getAttributeNS("http://www.w3.org/XML/1998/namespace", "lang"), current_element.textContent];
                            break;
                        case "splash":
                            Dictionary.splashes[Dictionary.splashes.length] = [current_element.getAttributeNS("http://www.w3.org/XML/1998/namespace", "lang"), current_element.textContent];
                            break;

                    }
                    break;
                case "affix":
                case "word":
                    lemma_name = current_element.getAttributeNS("http://leaf.faint.xyz/lexisml", "lemma").replace(/[0-9:]/g, "-");
                    current_forms = current_element.getElementsByTagNameNS("http://leaf.faint.xyz/lexisml", "form");
                    current_meanings = current_element.getElementsByTagNameNS("http://leaf.faint.xyz/lexisml", "meaning");
                    if (Dictionary.lemmas[lemma_name] === undefined) Dictionary.lemmas[lemma_name] = [];
                    lemma_id = lemma_name + ":" + Dictionary.lemmas[lemma_name].length;
                    lemma_class = "";
                    lemma_forms = [];
                    lemma_meanings = [];
                    for (j = 0; j < current_forms.length; j++) {
                        lemma_forms[j] = {
                            name: current_forms.item(j).textContent,
                            class: current_forms.item(j).getAttributeNS("http://leaf.faint.xyz/lexisml", "class")
                        }
                        if (current_forms.item(j).hasAttributeNS("http://leaf.faint.xyz/lexisml", "class")) lemma_class += current_forms.item(j).getAttributeNS("http://leaf.faint.xyz/lexisml", "class") + " ";
                        lemma_class = lemma_class.trim();
                        if (Dictionary.forms[current_forms.item(j).textContent] === undefined) Dictionary.forms[current_forms.item(j).textContent] = [];
                        Dictionary.forms[current_forms.item(j).textContent][Dictionary.forms[current_forms.item(j).textContent].length] = lemma_id;
                    }
                    for (j = 0; j < current_meanings.length; j++) {
                        lemma_meanings[j] = {
                            content: current_meanings.item(j).textContent,
                            class: current_meanings.item(j).getAttributeNS("http://leaf.faint.xyz/lexisml", "class")
                        }
                    }
                    Dictionary.lemmas[lemma_name][Dictionary.lemmas[lemma_name].length] = {
                        name: lemma_name,
                        id: lemma_id,
                        lang: current_element.getAttributeNS("http://www.w3.org/XML/1998/namespace", "lang"),
                        class: lemma_class,
                        forms: lemma_forms,
                        etymology: current_element.getElementsByTagNameNS("http://leaf.faint.xyz/lexisml", "etymology").item(0),
                        meaning: lemma_meanings
                    }
                    Dictionary.ids[Dictionary.ids.length] = lemma_id;
                    break;
            }
        }
        Dictionary.ids.sort(function (a, b) {return String(a).localeCompare(String(b));});
        document.body.textContent = null;
        var main_article = document.createElement("article");
        document.title = Dictionary.title[1];
        document.getElementsByTagName("title").item(0).lang = Dictionary.title[0]
        i = Math.floor(Math.random()*Dictionary.splashes.length);
        main_article.innerHTML = "
" + Dictionary.title[1] + "

" + Dictionary.splashes[i][1] + "
";
        for (i = 0; i < Dictionary.ids.length; i++) {
            current_element = document.createElement("article");
            current_lemma = Dictionary.getLemmaFromId(Dictionary.ids[i]);
            current_element.lang = current_lemma.lang;
            current_element.id = Dictionary.ids[i];
            article_html = "";
            article_html += ""
            article_html += "
" + current_lemma.name + "
"
            article_html += ""
            current_element.innerHTML = article_html;
            main_article.appendChild(current_element);
        }
    },
    splashes: [],
    title: "",
    title_lang: ""
}

window.addEventListener("load", Dictionary.init, false);
<commit_msg>splashes now optional<commit_after>/* jslint asi:true, browser:true */

if (typeof Lexis == "undefined") var Lexis = {};

var Dictionary = {
    forms: {},
    getLemmaFromId: function(id) {
        return Dictionary.lemmas[id.split(":")[0]][Number(id.split(":")[1])]
    },
    ids: [],
    init: function() {
        var script = document.createElement("script");
        script.type = "text/javascript";
        script.addEventListener("load", function() {Dictionary.load(document.documentElement.dataset.src)}, false);
        document.head.appendChild(script);
        script.src = "http://leaf.faint.xyz/langdev/!DATA!/master/!DATA!/LexisML/scripts/normalize.js";
    },
    lang: "",
    lemmas: {},
    lexis: undefined,
    load: function(src) {
        Dictionary.Requester.addEventListener("load", Dictionary.setup, false);
        Dictionary.Requester.open("get", src, true);
        Dictionary.Requester.overrideMimeType("text/xml");
        Dictionary.Requester.send();
    },
    Requester: new XMLHttpRequest(),
    setup: function() {
        Dictionary.lang = document.documentElement.lang;
        Dictionary.lexis = Dictionary.Requester.responseXML;
        Lexis.normalize(Dictionary.lexis);
        var i = 0;
        var j = 0;
        var elements = Dictionary.lexis.documentElement.children;
        var current_element;
        var current_forms;
        var current_meanings;
        var current_lemma;
        var lemma_name;
        var lemma_id;
        var lemma_class;
        var lemma_forms;
        var lemma_meanings;
        var article_html;
        for (i = 0; i < elements.length; i++) {
            current_element = elements.item(i);
            switch (current_element.tagName) {
                case "meta":
                    switch (current_element.getAttributeNS("http://leaf.faint.xyz/lexisml", "name")) {
                        case "title":
                            Dictionary.title = [current_element.getAttributeNS("http://www.w3.org/XML/1998/namespace", "lang"), current_element.textContent];
                            break;
                        case "splash":
                            Dictionary.splashes[Dictionary.splashes.length] = [current_element.getAttributeNS("http://www.w3.org/XML/1998/namespace", "lang"), current_element.textContent];
                            console.log("SPLASHED!");
                            break;

                    }
                    break;
                case "affix":
                case "word":
                    lemma_name = current_element.getAttributeNS("http://leaf.faint.xyz/lexisml", "lemma").replace(/[0-9:]/g, "-");
                    current_forms = current_element.getElementsByTagNameNS("http://leaf.faint.xyz/lexisml", "form");
                    current_meanings = current_element.getElementsByTagNameNS("http://leaf.faint.xyz/lexisml", "meaning");
                    if (Dictionary.lemmas[lemma_name] === undefined) Dictionary.lemmas[lemma_name] = [];
                    lemma_id = lemma_name + ":" + Dictionary.lemmas[lemma_name].length;
                    lemma_class = "";
                    lemma_forms = [];
                    lemma_meanings = [];
                    for (j = 0; j < current_forms.length; j++) {
                        lemma_forms[j] = {
                            name: current_forms.item(j).textContent,
                            class: current_forms.item(j).getAttributeNS("http://leaf.faint.xyz/lexisml", "class")
                        }
                        if (current_forms.item(j).hasAttributeNS("http://leaf.faint.xyz/lexisml", "class")) lemma_class += current_forms.item(j).getAttributeNS("http://leaf.faint.xyz/lexisml", "class") + " ";
                        lemma_class = lemma_class.trim();
                        if (Dictionary.forms[current_forms.item(j).textContent] === undefined) Dictionary.forms[current_forms.item(j).textContent] = [];
                        Dictionary.forms[current_forms.item(j).textContent][Dictionary.forms[current_forms.item(j).textContent].length] = lemma_id;
                    }
                    for (j = 0; j < current_meanings.length; j++) {
                        lemma_meanings[j] = {
                            content: current_meanings.item(j).textContent,
                            class: current_meanings.item(j).getAttributeNS("http://leaf.faint.xyz/lexisml", "class")
                        }
                    }
                    Dictionary.lemmas[lemma_name][Dictionary.lemmas[lemma_name].length] = {
                        name: lemma_name,
                        id: lemma_id,
                        lang: current_element.getAttributeNS("http://www.w3.org/XML/1998/namespace", "lang"),
                        class: lemma_class,
                        forms: lemma_forms,
                        etymology: current_element.getElementsByTagNameNS("http://leaf.faint.xyz/lexisml", "etymology").item(0),
                        meaning: lemma_meanings
                    }
                    Dictionary.ids[Dictionary.ids.length] = lemma_id;
                    break;
            }
        }
        Dictionary.ids.sort(function (a, b) {return String(a).localeCompare(String(b));});
        document.body.textContent = null;
        var main_article = document.createElement("article");
        document.title = Dictionary.title[1];
        document.getElementsByTagName("title").item(0).lang = Dictionary.title[0];
        if (Dictionary.splashes.length) {
            i = Math.floor(Math.random()*Dictionary.splashes.length);
            main_article.innerHTML = "
" + Dictionary.title[1] + "

" + Dictionary.splashes[i][1] + "
";
        }
        else main_article.innerHTML = "
" + Dictionary.title[1] + "
";
        for (i = 0; i < Dictionary.ids.length; i++) {
            current_element = document.createElement("article");
            current_lemma = Dictionary.getLemmaFromId(Dictionary.ids[i]);
            current_element.lang = current_lemma.lang;
            current_element.id = Dictionary.ids[i];
            article_html = "";
            article_html += ""
            article_html += "
" + current_lemma.name + "
"
            article_html += ""
            current_element.innerHTML = article_html;
            main_article.appendChild(current_element);
        }
    },
    splashes: [],
    title: "",
    title_lang: ""
}

window.addEventListener("load", Dictionary.init, false);
<|endoftext|>


<commit_before>/**
 * A list over all owned posts/needs with their connections
 * below each other. Usually limited to a connections of a
 * specific state (e.g. "hint")
 * Created by ksinger on 12.04.2017.
 */

import won from '../won-es6.js';
import angular from 'angular';
import squareImageModule from './square-image.js';
import connectionSelectionModule from './connection-selection.js';
import postHeaderModule from './post-header.js';

import {
    labels,
} from '../won-label-utils.js';

import { attach } from '../utils.js';
import {
    connect2Redux,
} from '../won-utils.js';
import { actionCreators }  from '../actions/actions.js';

import {
    selectAllOwnNeeds,
    selectRouterParams,
    selectNeedByConnectionUri,
} from '../selectors.js';

const serviceDependencies = ['$ngRedux', '$scope'];
function genComponentConf() {
    let template = `

          <won-post-header
            need-uri="need.get('uri')"
            timestamp="'TODOlatestOfThatType'">
          </won-post-header>

            {{self.getUnreadConnectionsCount(need)}}

        <won-connection-selection-item
          ng-show="self.isOpen(need.get('uri'))"
          ng-repeat="conn in self.getOpenConnectionsArray(need)"
          on-selected-connection="self.selectConnection(connectionUri)"
          connection-uri="conn.get('uri')"
          ng-class="{'won-unread': conn.get('unread')}">
        </won-connection-selection-item>

    `;

    class Controller {
        constructor() {
            attach(this, serviceDependencies, arguments);

            //this.labels = labels;
            this.open = open;
            window.co4dbg = this;

            const self = this;
            const selectFromState = (state)=> {
                //Select all needs with at least one connection
                const relevantOwnNeeds = selectAllOwnNeeds(state).filter(need => need.get("connections").filter(conn => conn.get("state") !== won.WON.Closed).size > 0);
                const routerParams = selectRouterParams(state);
                const connUriInRoute = routerParams && decodeURIComponent(routerParams['connectionUri']);
                const needImpliedInRoute = connUriInRoute && selectNeedByConnectionUri(state, connUriInRoute);

                return {
                    needImpliedInRoute,
                    relevantOwnNeeds: relevantOwnNeeds && relevantOwnNeeds.toArray(),
                }
            };
            connect2Redux(selectFromState, actionCreators, [], this);
        }
        toggleConnections(ownNeedUri) {
            this.open[ownNeedUri] = !this.open[ownNeedUri]
        }
        isOpen(ownNeedUri) {
            return !!this.open[ownNeedUri];
        }
        selectConnection(connectionUri) {
            this.onSelectedConnection({connectionUri}); //trigger callback with scope-object
        }
        getOpenConnectionsArray(need){
            return need.get('connections').filter(conn => conn.get('state') !== won.WON.Closed).toArray();
        }
        getUnreadConnectionsCount(need){
            const unreadConnections = need && need.get('connections').filter(conn => conn.get('unread') && conn.get('state') !== won.WON.Closed);
            return unreadConnections && unreadConnections.size > 0 ? unreadConnections.size : undefined;
        }
    }
    Controller.$inject = serviceDependencies;
    return {
        restrict: 'E',
        controller: Controller,
        controllerAs: 'self',
        bindToController: true, //scope-bindings -> ctrl
        scope: {
            open: "=",
            //connectionType: "=",
            /*
             * Usage:
             *  on-selected-connection="myCallback(connectionUri)"
             */
            onSelectedConnection: "&"
        },
        template: template
    }

}

export default angular.module('won.owner.components.connectionsOverview', [
        squareImageModule,
        connectionSelectionModule,
        postHeaderModule,
    ])
    .directive('wonConnectionsOverview', genComponentConf)
    .name;
<commit_msg>added sorting of chats-overview<commit_after>/**
 * A list over all owned posts/needs with their connections
 * below each other. Usually limited to a connections of a
 * specific state (e.g. "hint")
 * Created by ksinger on 12.04.2017.
 */

import won from '../won-es6.js';
import angular from 'angular';
import squareImageModule from './square-image.js';
import connectionSelectionModule from './connection-selection.js';
import postHeaderModule from './post-header.js';

import {
    labels,
} from '../won-label-utils.js';

import { attach } from '../utils.js';
import {
    connect2Redux,
} from '../won-utils.js';
import { actionCreators }  from '../actions/actions.js';

import {
    selectAllOwnNeeds,
    selectRouterParams,
    selectNeedByConnectionUri,
} from '../selectors.js';

const serviceDependencies = ['$ngRedux', '$scope'];
function genComponentConf() {
    let template = `

          <won-post-header
            need-uri="need.get('uri')"
            timestamp="'TODOlatestOfThatType'">
          </won-post-header>

            {{self.getUnreadConnectionsCount(need)}}

        <won-connection-selection-item
          ng-show="self.isOpen(need.get('uri'))"
          ng-repeat="conn in self.getOpenConnectionsArraySorted(need)"
          on-selected-connection="self.selectConnection(connectionUri)"
          connection-uri="conn.get('uri')"
          ng-class="{'won-unread': conn.get('unread')}">
        </won-connection-selection-item>

    `;

    class Controller {
        constructor() {
            attach(this, serviceDependencies, arguments);

            //this.labels = labels;
            this.open = open;
            window.co4dbg = this;

            const self = this;
            const selectFromState = (state)=> {
                //Select all needs with at least one connection
                const relevantOwnNeeds = selectAllOwnNeeds(state).filter(need => need.get("connections").filter(conn => conn.get("state") !== won.WON.Closed).size > 0);
                const routerParams = selectRouterParams(state);
                const connUriInRoute = routerParams && decodeURIComponent(routerParams['connectionUri']);
                const needImpliedInRoute = connUriInRoute && selectNeedByConnectionUri(state, connUriInRoute);

                let sortedNeeds = relevantOwnNeeds && relevantOwnNeeds.toArray();
                if(sortedNeeds) {
                    sortedNeeds.sort(function(a,b) {
                        const bDate = b.get("lastUpdateDate") && b.get("lastUpdateDate").getTime();
                        const aDate = a.get("lastUpdateDate") && a.get("lastUpdateDate").getTime();

                        return bDate - aDate;
                    });
                }

                return {
                    needImpliedInRoute,
                    sortedNeeds: sortedNeeds,
                }
            };
            connect2Redux(selectFromState, actionCreators, [], this);
        }
        toggleConnections(ownNeedUri) {
            this.open[ownNeedUri] = !this.open[ownNeedUri]
        }
        isOpen(ownNeedUri) {
            return !!this.open[ownNeedUri];
        }
        selectConnection(connectionUri) {
            this.onSelectedConnection({connectionUri}); //trigger callback with scope-object
        }

        getOpenConnectionsArraySorted(need){
            let sortedConnections = this.getOpenConnectionsArray(need);

            if(sortedConnections) {
                sortedConnections.sort(function(a,b) {
                    const bDate = b.get("lastUpdateDate") && b.get("lastUpdateDate").getTime();
                    const aDate = a.get("lastUpdateDate") && a.get("lastUpdateDate").getTime();

                    return bDate - aDate;
                });
            }

            return sortedConnections;
        }

        getOpenConnectionsArray(need) {
            return need.get('connections').filter(conn => conn.get('state') !== won.WON.Closed).toArray();
        }

        getUnreadConnectionsCount(need){
            const unreadConnections = need && need.get('connections').filter(conn => conn.get('unread') && conn.get('state') !== won.WON.Closed);
            return unreadConnections && unreadConnections.size > 0 ? unreadConnections.size : undefined;
        }
    }
    Controller.$inject = serviceDependencies;
    return {
        restrict: 'E',
        controller: Controller,
        controllerAs: 'self',
        bindToController: true, //scope-bindings -> ctrl
        scope: {
            open: "=",
            //connectionType: "=",
            /*
             * Usage:
             *  on-selected-connection="myCallback(connectionUri)"
             */
            onSelectedConnection: "&"
        },
        template: template
    }

}

export default angular.module('won.owner.components.connectionsOverview', [
        squareImageModule,
        connectionSelectionModule,
        postHeaderModule,
    ])
    .directive('wonConnectionsOverview', genComponentConf)
    .name;
<|endoftext|>


<commit_before>Application.Controllers.controller('projectsOverviewProvenance',
    ["$scope", "$stateParams", "mcapi", function ($scope, $stateParams,mcapi) {
        $scope.sampleDetails = function(branch){
            mcapi('/objects/%', branch.id)
                .success(function (data) {
                    $scope.details = data;
                }).jsonp();
            mcapi('/processes/sample/%', branch.id)
                .success(function (data) {
                    $scope.processes = data;
                }).jsonp();

        };

        $scope.processDetails = function(p_id){
            mcapi('/processes/%', p_id)
                .success(function (data) {
                    $scope.process = [];
                    $scope.process.push(data);
                })
                .error(function(e){
                }).jsonp();
        };

        function init() {
            $scope.project_id = $stateParams.id;
            $scope.my_tree =  {};
            mcapi('/samples/%/tree', $scope.project_id)
                .success(function (data) {
                    $scope.tree_data = data;
                    $scope.col_defs = [
                        { field: "path"},
                        { field: "owner"},
                        {field: "level"}
                    ];
                }).jsonp();
        }
        init();
    }]);
<commit_msg>ISSUE#494. Sort top level names.<commit_after>Application.Controllers.controller('projectsOverviewProvenance',
    ["$scope", "$stateParams", "mcapi", "$filter", function ($scope, $stateParams,mcapi, $filter) {
        $scope.sampleDetails = function(branch){
            mcapi('/objects/%', branch.id)
                .success(function (data) {
                    $scope.details = data;
                }).jsonp();
            mcapi('/processes/sample/%', branch.id)
                .success(function (data) {
                    $scope.processes = data;
                }).jsonp();

        };

        $scope.processDetails = function(p_id){
            mcapi('/processes/%', p_id)
                .success(function (data) {
                    $scope.process = [];
                    $scope.process.push(data);
                })
                .error(function(e){
                }).jsonp();
        };

        function init() {
            $scope.project_id = $stateParams.id;
            $scope.my_tree =  {};
            mcapi('/samples/%/tree', $scope.project_id)
                .success(function (data) {
                    // Partial fix to sorting the samples. This only sorts the top level.
                    $scope.tree_data = $filter('orderBy')(data, 'name');
                    $scope.col_defs = [
                        { field: "path"},
                        { field: "owner"},
                        {field: "level"}
                    ];
                }).jsonp();
        }
        init();
    }]);
<|endoftext|>


<commit_before>#!/usr/bin/env node

/*
 *
 * Copyright 2013 Canonical Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
*/

var shell = require('shelljs');
var path = require('path');
var fs = require('fs');
var msg = require('./msg');
var assert = require('assert');
var colors = require('colors');

function exec(cmd) {
    console.log(cmd.green);

    var res = shell.exec(cmd);
    if (res.code !== 0) {
        console.error(cmd.green + " " + "FAILED".underline.red);
        process.exit(1);
    }

    return res;
}

function cp(source, dest) {
    console.log(('cp -Rf ' + source + ' ' + dest).green);

    if (shell.cp('-r', source, dest) === null) {
        console.error("FAILED".underline.red);
        process.exit(1);
    }
}

function pushd(dir) {
    console.log(('pushd ' + dir).green);
    shell.pushd(dir);
}

function popd(dir) {
    console.log(('popd').green);
    shell.popd();
}

function buildArmPackage(campoDir, ubuntuDir, nobuild) {
    var armhfDir = path.join(ubuntuDir, 'armhf');
    var prefixDir = path.join(armhfDir, 'prefix');

    if (nobuild && fs.existsSync(path.join(prefixDir, 'cordova-ubuntu'))) {
        return;
    }

    shell.rm('-rf', path.join(armhfDir, 'build'));

    shell.rm('-rf', prefixDir);
    shell.mkdir(path.join(armhfDir, 'build'));
    shell.mkdir(prefixDir);

    pushd(path.join(armhfDir, 'build'));

    exec('click chroot -aarmhf -s trusty run cmake ' + campoDir + ' -DCMAKE_TOOLCHAIN_FILE=/etc/dpkg-cross/cmake/CMakeCross.txt -DCMAKE_INSTALL_PREFIX="' + prefixDir + '"');
    exec('find . -name AutomocInfo.cmake | xargs sed -i \'s;AM_QT_MOC_EXECUTABLE .*;AM_QT_MOC_EXECUTABLE "/usr/lib/\'$(dpkg-architecture -qDEB_BUILD_MULTIARCH)\'/qt5/bin/moc");\'');
    exec('click chroot -aarmhf -s trusty run make -j 6');
    exec('click chroot -aarmhf -s trusty run make install');
    cp(path.join(ubuntuDir, 'www', '*'), path.join(prefixDir, 'www'));
    cp(path.join(ubuntuDir, 'qml', '*'), path.join(prefixDir, 'qml'));
    cp(path.join(ubuntuDir, 'apparmor.json'), prefixDir);
    cp(path.join(ubuntuDir, 'cordova.desktop'), prefixDir);
    cp(path.join(ubuntuDir, 'config.xml'), prefixDir);

    var content = JSON.parse(fs.readFileSync(path.join(ubuntuDir, 'manifest.json'), {encoding: "utf8"}));
    content.architecture = "armhf";
    fs.writeFileSync(path.join(prefixDir, 'manifest.json'), JSON.stringify(content));

    pushd(prefixDir);

    exec('click build .');

    popd();

    popd();
}

function buildNative(campoDir, ubuntuDir, nobuild) {
    var nativeDir = path.join(ubuntuDir, 'native');
    var prefixDir = path.join(nativeDir, 'prefix');

    if (nobuild && fs.existsSync(path.join(prefixDir, 'cordova-ubuntu'))) {
        return;
    }

    shell.rm('-rf', path.join(nativeDir, 'build'));
    shell.rm('-rf', prefixDir);

    shell.mkdir(path.join(nativeDir, 'build'));
    shell.mkdir(prefixDir);

    pushd(path.join(nativeDir, 'build'));

    exec('cmake ' + campoDir + ' -DCMAKE_INSTALL_PREFIX="' + prefixDir + '"');
    exec('make -j 6; make install');

    cp(path.join(ubuntuDir, 'config.xml'), prefixDir);
    cp(path.join(ubuntuDir, 'www', '*'), path.join(prefixDir, 'www'));
    cp(path.join(ubuntuDir, 'qml', '*'), path.join(prefixDir, 'qml'));

    popd();
}

module.exports.ALL = 2;
module.exports.PHONE = 0;
module.exports.DESKTOP = 1;

module.exports.build = function(rootDir, target, nobuild) {
    var ubuntuDir = path.join(rootDir, 'platforms', 'ubuntu');
    var campoDir = path.join(ubuntuDir, 'build');

    assert.ok(fs.existsSync(ubuntuDir));
    assert.ok(fs.existsSync(campoDir));

    if (target === module.exports.PHONE || target === module.exports.ALL)
        buildArmPackage(campoDir, ubuntuDir, nobuild);
    if (target === module.exports.DESKTOP || target === module.exports.ALL)
        buildNative(campoDir, ubuntuDir, nobuild);
}

function runNative(rootDir, debug) {
    var ubuntuDir = path.join(rootDir, 'platforms', 'ubuntu');
    var nativeDir = path.join(ubuntuDir, 'native');

    pushd(path.join(nativeDir, 'prefix'));

    if (debug) {
        console.error('Debug enabled. Try pointing a WebKit browser to http://127.0.0.1:9222');
        exec('QTWEBKIT_INSPECTOR_SERVER=9222 ./cordova-ubuntu www/');
    } else {
        exec('./cordova-ubuntu www/');
    }

    popd();
}

function deviceList() {
    var res = exec('adb devices');

    var response = res.output.split('\n');
    var deviceList = [];

    for (var i = 1; i < response.length; i++) {
        if (response[i].match(/\w+\tdevice/)) {
            deviceList.push(response[i].replace(/\tdevice/, '').replace('\r', ''));
        }
    }

    return deviceList;
}

function adbExec(target, command) {
    assert.ok(target && command);
    return exec('adb -s ' + target + ' ' + command);
}

function isDeviceAttached(target) {
    var res = adbExec(target, 'get-state');

    if (res.output.indexOf('device') == -1)
        return false;

    res = adbExec(target, 'shell uname -a');
    if (res.output.indexOf('ubuntu-phablet') == -1)
        return false;

    return true;
}

function runOnDevice(rootDir, debug, target) {
    var ubuntuDir = path.join(rootDir, 'platforms', 'ubuntu');

    if (!isDeviceAttached(target)) {
        console.error(msg.UBUNTU_TOUCH_DEVICE_NOT_AVALIABLE.red)
        process.exit(1);
    }

    var armhfDir = path.join(ubuntuDir, 'armhf');
    var prefixDir = path.join(armhfDir, 'prefix');

    pushd(prefixDir);

    var manifest = JSON.parse(fs.readFileSync(path.join(ubuntuDir, 'manifest.json'), {encoding: "utf8"}));
    var appId = manifest.name;

    var names = shell.ls().filter(function (name) {
        return name.indexOf(appId) == 0 && name.indexOf('.click');
    });

    assert.ok(names.length == 1);

    adbExec(target, 'shell "ps -A -eo pid,cmd | grep cordova-ubuntu | awk \'{ print \\$1 }\' | xargs kill -9"')

    if (debug)
        adbExec(target, 'forward --remove-all');

    adbExec(target, 'push ' + names[0] + ' /home/phablet');
    adbExec(target, 'shell "cd /home/phablet/; click install ' + names[0] + ' --user=phablet"');

    if (debug) {
        console.error('Debug enabled. Try pointing a WebKit browser to http://127.0.0.1:9222');

        adbExec(target, 'forward tcp:9222 tcp:9222');
    }

    adbExec(target, 'shell "su - phablet -c \'cd /opt/click.ubuntu.com/' + appId + '/current; QTWEBKIT_INSPECTOR_SERVER=9222 ./cordova-ubuntu www/ --desktop_file_hint=/opt/click.ubuntu.com/' + appId + '/current/cordova.desktop\'"');

    popd();

    console.log('have fun!'.rainbow);
}

module.exports.run = function(rootDir, desktop, debug, target, nobuild) {
    if (desktop) {
        module.exports.build(rootDir, module.exports.DESKTOP, nobuild);
        runNative(rootDir, debug);
    } else {
        if (!target) {
            var devices = deviceList();

            if (!devices.length) {
                console.error(msg.UBUNTU_TOUCH_DEVICE_NOT_AVALIABLE.red)
                process.exit(1);
            }

            target = devices[0];

            if (devices.length > 1) {
                console.warn('you can specify target with --target <device id>'.yellow);
                console.warn(('running on ' + target).yellow);
            }
        }

        module.exports.build(rootDir, module.exports.PHONE, nobuild);
        runOnDevice(rootDir, debug, target);
    }
}
<commit_msg>bin/build/build: generate deb package<commit_after>#!/usr/bin/env node

/*
 *
 * Copyright 2013 Canonical Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
*/

var shell = require('shelljs');
var path = require('path');
var fs = require('fs');
var msg = require('./msg');
var assert = require('assert');
var colors = require('colors');

function exec(cmd) {
    console.log(cmd.green);

    var res = shell.exec(cmd);
    if (res.code !== 0) {
        console.error(cmd.green + " " + "FAILED".underline.red);
        process.exit(1);
    }

    return res;
}

function cp(source, dest) {
    console.log(('cp -Rf ' + source + ' ' + dest).green);

    if (shell.cp('-r', source, dest) === null) {
        console.error("FAILED".underline.red);
        process.exit(1);
    }
}

function pushd(dir) {
    console.log(('pushd ' + dir).green);
    shell.pushd(dir);
}

function popd(dir) {
    console.log(('popd').green);
    shell.popd();
}

function buildArmPackage(campoDir, ubuntuDir, nobuild) {
    var armhfDir = path.join(ubuntuDir, 'armhf');
    var prefixDir = path.join(armhfDir, 'prefix');

    if (nobuild && fs.existsSync(path.join(prefixDir, 'cordova-ubuntu'))) {
        return;
    }

    shell.rm('-rf', path.join(armhfDir, 'build'));

    shell.rm('-rf', prefixDir);
    shell.mkdir(path.join(armhfDir, 'build'));
    shell.mkdir(prefixDir);

    pushd(path.join(armhfDir, 'build'));

    exec('click chroot -aarmhf -s trusty run cmake ' + campoDir + ' -DCMAKE_TOOLCHAIN_FILE=/etc/dpkg-cross/cmake/CMakeCross.txt -DCMAKE_INSTALL_PREFIX="' + prefixDir + '"');
    exec('find . -name AutomocInfo.cmake | xargs sed -i \'s;AM_QT_MOC_EXECUTABLE .*;AM_QT_MOC_EXECUTABLE "/usr/lib/\'$(dpkg-architecture -qDEB_BUILD_MULTIARCH)\'/qt5/bin/moc");\'');
    exec('click chroot -aarmhf -s trusty run make -j 6');
    exec('click chroot -aarmhf -s trusty run make install');
    cp(path.join(ubuntuDir, 'www', '*'), path.join(prefixDir, 'www'));
    cp(path.join(ubuntuDir, 'qml', '*'), path.join(prefixDir, 'qml'));
    cp(path.join(ubuntuDir, 'apparmor.json'), prefixDir);
    cp(path.join(ubuntuDir, 'cordova.desktop'), prefixDir);
    cp(path.join(ubuntuDir, 'config.xml'), prefixDir);

    var content = JSON.parse(fs.readFileSync(path.join(ubuntuDir, 'manifest.json'), {encoding: "utf8"}));
    content.architecture = "armhf";
    fs.writeFileSync(path.join(prefixDir, 'manifest.json'), JSON.stringify(content));

    pushd(prefixDir);

    exec('click build .');

    popd();

    popd();
}

function buildNative(campoDir, ubuntuDir, nobuild) {
    var nativeDir = path.join(ubuntuDir, 'native');
    var prefixDir = path.join(nativeDir, 'prefix');

    if (nobuild && fs.existsSync(path.join(prefixDir, 'cordova-ubuntu'))) {
        return;
    }

    shell.rm('-rf', path.join(nativeDir, 'build'));
    shell.rm('-rf', prefixDir);

    shell.mkdir(path.join(nativeDir, 'build'));
    shell.mkdir(prefixDir);

    pushd(path.join(nativeDir, 'build'));

    exec('cmake ' + campoDir + ' -DCMAKE_INSTALL_PREFIX="' + prefixDir + '"');
    exec('make -j 6; make install');

    cp(path.join(ubuntuDir, 'config.xml'), prefixDir);
    cp(path.join(ubuntuDir, 'www', '*'), path.join(prefixDir, 'www'));
    cp(path.join(ubuntuDir, 'qml', '*'), path.join(prefixDir, 'qml'));

    popd();

    var manifest = JSON.parse(fs.readFileSync(path.join(ubuntuDir, 'manifest.json'), {encoding: "utf8"}));

    assert(manifest.name.length);
    assert(manifest.name.indexOf(' ') == -1);

    var debDir = path.join(nativeDir, manifest.name);

    shell.rm('-rf', debDir);
    shell.mkdir('-p', path.join(debDir, 'opt', manifest.name));
    cp(path.join(prefixDir, '*'), path.join(debDir, 'opt', manifest.name));

    var destDir = path.join('/opt', manifest.name);
    shell.mkdir('-p', path.join(debDir, 'usr', 'share', 'applications'));
    shell.mkdir('-p', path.join(debDir, 'DEBIAN'));
    fs.writeFileSync(path.join(debDir, 'DEBIAN', 'control'), 'Package: ' + manifest.name + '\nVersion: ' + manifest.version + '\nMaintainer: ' + manifest.maintainer + '\nArchitecture: ' + manifest.architecture + '\nDescription: ' + manifest.description + '\n')
    fs.writeFileSync(path.join(debDir, 'usr', 'share', 'applications', manifest.name + '.desktop'), '[Desktop Entry]\nName=' + manifest.title + '\nExec=' + path.join(destDir, 'cordova-ubuntu') + ' ' + path.join(destDir, 'www') + '\nIcon=qmlscene\nTerminal=false\nType=Application\nX-Ubuntu-Touch=true\n');

    pushd(nativeDir);

    exec('dpkg-deb -b "' + manifest.name + '" .');
    shell.rm('-rf', debDir);

    popd();
}

module.exports.ALL = 2;
module.exports.PHONE = 0;
module.exports.DESKTOP = 1;

module.exports.build = function(rootDir, target, nobuild) {
    var ubuntuDir = path.join(rootDir, 'platforms', 'ubuntu');
    var campoDir = path.join(ubuntuDir, 'build');

    assert.ok(fs.existsSync(ubuntuDir));
    assert.ok(fs.existsSync(campoDir));

    if (target === module.exports.PHONE || target === module.exports.ALL)
        buildArmPackage(campoDir, ubuntuDir, nobuild);
    if (target === module.exports.DESKTOP || target === module.exports.ALL)
        buildNative(campoDir, ubuntuDir, nobuild);
}

function runNative(rootDir, debug) {
    var ubuntuDir = path.join(rootDir, 'platforms', 'ubuntu');
    var nativeDir = path.join(ubuntuDir, 'native');

    pushd(path.join(nativeDir, 'prefix'));

    if (debug) {
        console.error('Debug enabled. Try pointing a WebKit browser to http://127.0.0.1:9222');
        exec('QTWEBKIT_INSPECTOR_SERVER=9222 ./cordova-ubuntu www/');
    } else {
        exec('./cordova-ubuntu www/');
    }

    popd();
}

function deviceList() {
    var res = exec('adb devices');

    var response = res.output.split('\n');
    var deviceList = [];

    for (var i = 1; i < response.length; i++) {
        if (response[i].match(/\w+\tdevice/)) {
            deviceList.push(response[i].replace(/\tdevice/, '').replace('\r', ''));
        }
    }

    return deviceList;
}

function adbExec(target, command) {
    assert.ok(target && command);
    return exec('adb -s ' + target + ' ' + command);
}

function isDeviceAttached(target) {
    var res = adbExec(target, 'get-state');

    if (res.output.indexOf('device') == -1)
        return false;

    res = adbExec(target, 'shell uname -a');
    if (res.output.indexOf('ubuntu-phablet') == -1)
        return false;

    return true;
}

function runOnDevice(rootDir, debug, target) {
    var ubuntuDir = path.join(rootDir, 'platforms', 'ubuntu');

    if (!isDeviceAttached(target)) {
        console.error(msg.UBUNTU_TOUCH_DEVICE_NOT_AVALIABLE.red)
        process.exit(1);
    }

    var armhfDir = path.join(ubuntuDir, 'armhf');
    var prefixDir = path.join(armhfDir, 'prefix');

    pushd(prefixDir);

    var manifest = JSON.parse(fs.readFileSync(path.join(ubuntuDir, 'manifest.json'), {encoding: "utf8"}));
    var appId = manifest.name;

    var names = shell.ls().filter(function (name) {
        return name.indexOf(appId) == 0 && name.indexOf('.click');
    });

    assert.ok(names.length == 1);

    adbExec(target, 'shell "ps -A -eo pid,cmd | grep cordova-ubuntu | awk \'{ print \\$1 }\' | xargs kill -9"')

    if (debug)
        adbExec(target, 'forward --remove-all');

    adbExec(target, 'push ' + names[0] + ' /home/phablet');
    adbExec(target, 'shell "cd /home/phablet/; click install ' + names[0] + ' --user=phablet"');

    if (debug) {
        console.error('Debug enabled. Try pointing a WebKit browser to http://127.0.0.1:9222');

        adbExec(target, 'forward tcp:9222 tcp:9222');
    }

    adbExec(target, 'shell "su - phablet -c \'cd /opt/click.ubuntu.com/' + appId + '/current; QTWEBKIT_INSPECTOR_SERVER=9222 ./cordova-ubuntu www/ --desktop_file_hint=/opt/click.ubuntu.com/' + appId + '/current/cordova.desktop\'"');

    popd();

    console.log('have fun!'.rainbow);
}

module.exports.run = function(rootDir, desktop, debug, target, nobuild) {
    if (desktop) {
        module.exports.build(rootDir, module.exports.DESKTOP, nobuild);
        runNative(rootDir, debug);
    } else {
        if (!target) {
            var devices = deviceList();

            if (!devices.length) {
                console.error(msg.UBUNTU_TOUCH_DEVICE_NOT_AVALIABLE.red)
                process.exit(1);
            }

            target = devices[0];

            if (devices.length > 1) {
                console.warn('you can specify target with --target <device id>'.yellow);
                console.warn(('running on ' + target).yellow);
            }
        }

        module.exports.build(rootDir, module.exports.PHONE, nobuild);
        runOnDevice(rootDir, debug, target);
    }
}
<|endoftext|>


<commit_before>import React from 'react';
import firebase from 'firebase';
import SearchForm from '../components/search_form';
import TopicBlock from '../components/topic_block';

class HomePage extends React.Component {
	constructor(props) {
		super(props);
		this.state = {
			listOfQuizzes: [],
			filterText: '',
			matchingTheSearch: false,
			listOfMatchedQuizzes: [],
			currentUser: ''
		};
		this.handleUserInput = this.handleUserInput.bind(this);
		this.findMatches = this.findMatches.bind(this);
		this.populateQuizArray = this.populateQuizArray.bind(this);
	}

	componentDidMount() {
		this.populateQuizArray();
	}

	// function fetching data from firebase to display available quizzes
	populateQuizArray() {
		const firebaseRef = firebase.database().ref('quizzes');

		// loops through each quiz once and pushes it in listOfQuizzes
		let quizzes = [];
		firebaseRef.on('child_added', (snapshot) => {
			let quiz = {
				name: snapshot.key,
				details: snapshot.val()
			};
			quizzes.push(quiz);
			this.setState({ listOfQuizzes: quizzes });
		});
	}

	// function linked to Search Form
	handleUserInput(filterText, matchingTheSearch) {
	    this.setState({
	      filterText: filterText,
	      matchingTheSearch: this.state.matchingTheSearch
	    });

	    const matchArray = this.findMatches(filterText, this.state.listOfQuizzes);
	    // console.table([matchArray]);
	    // console.log('list o quizzes length ' +this.state.listOfQuizzes.length)
    	this.setState({matchingTheSearch: true, listOfMatchedQuizzes: [...matchArray]});

	    // if nothing is typed show everything
	    // if something is typed && there are matches display only those
	    // if there are no matches ask user to refine their search

	    if (matchArray.length >= 1) {
	    	console.log('a match exists');

	    } else if (matchArray.length === this.state.listOfQuizzes.length) {
	    	console.log('display all quizzes')
	    	this.setState({matchingTheSearch: false});

	    } else if (matchArray.length === 0 ) {
			console.log('there is no match');
			this.setState({matchingTheSearch: false});
	    }
	}

	findMatches(wordToMatch, quizzes){
		return quizzes.filter(quiz => {
			const rgex = new RegExp(wordToMatch, 'gi');
			// console.log({quiz: quiz.name});
			return quiz.name.match(rgex);
		});
	}

	render() {
		return (

Welcome to Nerdia Tech Trivia

					<SearchForm
						filterText={this.state.filterText}
						matchingTheSearch={this.state.matchingTheSearch}
						onUserInput={this.handleUserInput} />

						Welcome to Nerdia, { !this.props.isUserLoggedIn ? "Guest" : this.state.currentUser }

						{ /* matchingTheSearch == true ? console.log('true') : console.log(false)*/}

						{	this.state.listOfQuizzes.map( (quiz) => (
								<TopicBlock key={quiz.name}
											quizDetails={quiz}
											isUserLoggedIn={ this.props.isUserLoggedIn }
								/>
							)) }

		)
	}
}

export default HomePage;

<commit_msg>feat: filter quizzes by name homepage<commit_after>import React from 'react';
import firebase from 'firebase';
import SearchForm from '../components/search_form';
import TopicBlock from '../components/topic_block';

class HomePage extends React.Component {
	constructor(props) {
		super(props);
		this.state = {
			listOfQuizzes: [],
			filterText: '',
			matchingTheSearch: false,
			listOfMatchedQuizzes: [],
			currentUser: ''
		};
		this.handleUserInput = this.handleUserInput.bind(this);
		this.findMatches = this.findMatches.bind(this);
		this.populateQuizArray = this.populateQuizArray.bind(this);
	}

	componentDidMount() {
		this.populateQuizArray();
	}

	// function fetching data from firebase to display available quizzes
	populateQuizArray() {
		const firebaseRef = firebase.database().ref('quizzes');

		// loops through each quiz once and pushes it in listOfQuizzes
		let quizzes = [];
		firebaseRef.on('child_added', (snapshot) => {
			let quiz = {
				name: snapshot.key,
				details: snapshot.val()
			};
			quizzes.push(quiz);
			this.setState({ listOfQuizzes: quizzes });
		});
	}

	// function linked to Search Form
	handleUserInput(filterText, matchingTheSearch) {
	    this.setState({
	      filterText: filterText,
	      matchingTheSearch: this.state.matchingTheSearch
	    });

	    const matchArray = this.findMatches(filterText, this.state.listOfQuizzes);
    	this.setState({matchingTheSearch: true, listOfMatchedQuizzes: [...matchArray]});

	    // if nothing is typed show everything
	    // if something is typed && there are matches display only those
	    // if there are no matches ask user to refine their search
	    if (matchArray.length === this.state.listOfQuizzes.length) {
	    	console.log('display all quizzes')
	    	this.setState({matchingTheSearch: false});

	    } else if (matchArray.length >= 1 ) {
	    	console.log('a match exists');

	    } else if (matchArray.length === 0 ) {
			console.log('there is no match.');
			this.setState({matchingTheSearch: 'no match'});
	    }
	}

	findMatches(wordToMatch, quizzes){
		return quizzes.filter(quiz => {
			const rgex = new RegExp(wordToMatch, 'gi');
			return quiz.name.match(rgex);
		});
	}

	render() {
		return (

Welcome to Nerdia Tech Trivia

					<SearchForm
						filterText={this.state.filterText}
						matchingTheSearch={this.state.matchingTheSearch}
						onUserInput={this.handleUserInput} />

						Welcome to Nerdia, { !this.props.isUserLoggedIn ? "Guest" : this.state.currentUser }

						{ this.state.matchingTheSearch == true ?
							this.state.listOfMatchedQuizzes.map( (quiz) => (
								<TopicBlock key={quiz.name}
											quizDetails={quiz}
											isUserLoggedIn={ this.props.isUserLoggedIn }
								/>
							))
							: // else
							this.state.listOfQuizzes.map( (quiz) => (
								<TopicBlock key={quiz.name}
											quizDetails={quiz}
											isUserLoggedIn={ this.props.isUserLoggedIn }
								/>
							))
						 }

		)
	}
}

export default HomePage;

<|endoftext|>


<commit_before>'use strict';

var nunjucks      = require('nunjucks');
var _             = require('lodash');

var viewCache = {};

/**
 * Create a custom string loader and instantiate a new Nunjucks environment object with it.
 * We don't want to use the FileSystemLoader as we already have
 * the contents of all files cached in the component file tree.
 */

var StringLoader = nunjucks.Loader.extend({
    getSource: function(name) {
        var view = _.find(viewCache, function(view){
            return (view.handle === name || view.alias === name);
        });
        if (view) {
            return {
                src: view.content,
                path: view.path,
                noCache: true
            };
        }
        throw new Error('Partial template not found.');
    }
});

var nj = new nunjucks.Environment(new StringLoader(), {
    autoescape: false
});

module.exports = {

    defaults: {
        ext: ".nunjucks"
    },

    /**
     * Register any custom filters, globals and extensions set in the config.
     */

    extend: function(config){
        var extras = config.extend || {};
        _.each(extras.filters || {}, function(filter, name){
            nj.addFilter(name, filter);
        });
        _.each(extras.extensions || {}, function(ext, name){
            nj.addExtension(name, ext);
        });
        _.each(extras.globals || {}, function(value, name){
            nj.addGlobal(name, value);
        });
    },

    /**
     * Update view file cache.
     * Called every time the component file tree changes.
     */

    registerViews: function(views) {
        viewCache = views;
    },

    /**
     * Render the component view contents.
     */

    render: function(str, context, meta) {
        return nj.renderString(str, context);
    }

};
<commit_msg>Add name and change configure method<commit_after>'use strict';

var nunjucks      = require('nunjucks');
var _             = require('lodash');

var viewCache = {};

/**
 * Create a custom string loader and instantiate a new Nunjucks environment object with it.
 * We don't want to use the FileSystemLoader as we already have
 * the contents of all files cached in the component file tree.
 */

var StringLoader = nunjucks.Loader.extend({
    getSource: function(name) {
        var view = _.find(viewCache, function(view){
            return (view.handle === name || view.alias === name);
        });
        if (view) {
            return {
                src: view.content,
                path: view.path,
                noCache: true
            };
        }
        throw new Error('Partial template not found.');
    }
});

var nj = new nunjucks.Environment(new StringLoader(), {
    autoescape: false
});

module.exports = {

    defaults: {
        ext: ".nunjucks",
        name: "nunjucks"
    },

    /**
     * Register any custom filters, globals and extensions set in the config.
     */

    configure: function(config){
        var extras = config.extend || {};
        _.each(extras.filters || {}, function(filter, name){
            nj.addFilter(name, filter);
        });
        _.each(extras.extensions || {}, function(ext, name){
            nj.addExtension(name, ext);
        });
        _.each(extras.globals || {}, function(value, name){
            nj.addGlobal(name, value);
        });
    },

    /**
     * Update view file cache.
     * Called every time the component file tree changes.
     */

    registerViews: function(views) {
        viewCache = views;
    },

    /**
     * Render the component view contents.
     */

    render: function(str, context, meta) {
        return nj.renderString(str, context);
    }

};
<|endoftext|>


<commit_before>/**
 * GoogleChart component.
 *
 * Site Kit by Google, Copyright 2021 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/* eslint-disable react-hooks/exhaustive-deps */

/**
 * External dependencies
 */
import classnames from 'classnames';
import PropTypes from 'prop-types';
import { Chart } from 'react-google-charts';

/**
 * WordPress dependencies
 */
import { useEffect, useLayoutEffect, useRef } from '@wordpress/element';

/**
 * Internal dependencies
 */
import PreviewBlock from './PreviewBlock';

export default function GoogleChart( props ) {
	const {
		chartEvents,
		chartType,
		children,
		className,
		data,
		getChartWrapper,
		height,
		loaded,
		loadingHeight,
		loadingWidth,
		onMouseOver,
		onMouseOut,
		onReady,
		onSelect,
		selectedStats,
		width,
		...otherProps
	} = props;

	// Ensure we don't filter out columns that aren't data, but are things like
	// tooltips or other content.
	let nonDataColumns = [];
	if ( data?.length ) {
		nonDataColumns = data[ 0 ].reduce( ( acc, row, rowIndex ) => {
			return row?.role ? [ ...acc, rowIndex ] : acc;
		}, [] );
	}

	// If only certain columns should be displayed for the data set we have
	// then filter out that data.
	let modifiedData = data;
	if ( selectedStats?.length > 0 ) {
		modifiedData = data.map( ( row ) => {
			return row.filter( ( _columnValue, columnIndex ) => {
				return columnIndex === 0 || selectedStats.includes( columnIndex - 1 ) || nonDataColumns.includes( columnIndex - 1 );
			} );
		} );
	}

	let loadingHeightToUse = loadingHeight || height;
	let loadingWidthToUse = loadingWidth || width;
	// If a loading height is set but a width is not (or a loading width is set
	// but not a height), change the "unset" value to 100% to avoid visual bugs.
	// See: https://github.com/google/site-kit-wp/pull/2916#discussion_r623866269
	if ( loadingHeightToUse && ! loadingWidthToUse ) {
		loadingWidthToUse = '100%';
	}
	if ( loadingWidthToUse && ! loadingHeightToUse ) {
		loadingHeightToUse = '100%';
	}
	const loadingShape = chartType === 'PieChart' ? 'circular' : 'square';

	const loader = (

			<PreviewBlock
				className="googlesitekit-chart-loading__wrapper"
				height={ loadingHeightToUse }
				shape={ loadingShape }
				width={ loadingWidthToUse }
			/>

	);

	const chartWrapperRef = useRef();
	const googleRef = useRef();

	useEffect( () => {
		// Remove all event listeners after the component has unmounted.
		return () => {
			// eslint-disable-next-line no-unused-expressions
			if ( googleRef.current && chartWrapperRef.current ) {
				const { events } = googleRef.current.visualization;
				events.removeAllListeners( chartWrapperRef.current.getChart() );
				events.removeAllListeners( chartWrapperRef.current );
			}
		};
	}, [] );

	// These event listeners are added manually to the current chart because
	// `react-google-charts` doesn't support `mouseOver` or `mouseOut` events
	// in its `chartEvents` prop.
	// See: https://github.com/google/site-kit-wp/pull/2805#discussion_r579172660
	useLayoutEffect( () => {
		if ( onMouseOver ) {
			// eslint-disable-next-line no-unused-expressions
			googleRef.current?.visualization.events.addListener( chartWrapperRef.current.getChart(), 'onmouseover', ( event ) => {
				onMouseOver( event, {
					chartWrapper: chartWrapperRef.current,
					google: googleRef.current,
				} );
			} );
		}

		if ( onMouseOut ) {
			// eslint-disable-next-line no-unused-expressions
			googleRef.current?.visualization.events.addListener( chartWrapperRef.current.getChart(), 'onmouseout', ( event ) => {
				onMouseOut( event, {
					chartWrapper: chartWrapperRef.current,
					google: googleRef.current,
				} );
			} );
		}
	}, [ onMouseOver, onMouseOut ] );

	if ( ! loaded ) {
		return (

				{ loader }

		);
	}

	const combinedChartEvents = [ ...chartEvents || [] ];

	if ( onReady ) {
		combinedChartEvents.push( {
			eventName: 'ready',
			callback: onReady,
		} );
	}

	if ( onSelect ) {
		combinedChartEvents.push( {
			eventName: 'select',
			callback: onSelect,
		} );
	}

	return (
		<div
			className={ classnames(
				'googlesitekit-chart',
				`googlesitekit-chart--${ chartType }`,
				className
			) }
		>
			<Chart
				className="googlesitekit-chart__inner"
				chartEvents={ combinedChartEvents }
				chartType={ chartType }
				chartVersion="49"
				data={ modifiedData }
				loader={ loader }
				height={ height }
				getChartWrapper={ ( chartWrapper, google ) => {
					// Remove all the event listeners on the old chart before we draw
					// a new one. Only run this if the old chart and the new chart aren't
					// the same reference though, otherwise we'll remove existing `onReady`
					// events and other event listeners, which will cause bugs.
					if ( chartWrapper !== chartWrapperRef.current ) {
						// eslint-disable-next-line no-unused-expressions
						googleRef.current?.visualization.events.removeAllListeners( chartWrapperRef.current?.getChart() );
						// eslint-disable-next-line no-unused-expressions
						googleRef.current?.visualization.events.removeAllListeners( chartWrapperRef.current );
					}

					chartWrapperRef.current = chartWrapper;
					googleRef.current = google;

					if ( getChartWrapper ) {
						getChartWrapper( chartWrapper, google );
					}
				} }
				width={ width }
				{ ...otherProps }
			/>
			{ children }

	);
}

GoogleChart.propTypes = {
	className: PropTypes.string,
	children: PropTypes.node,
	chartEvents: PropTypes.arrayOf( PropTypes.shape( {
		eventName: PropTypes.string,
		callback: PropTypes.func,
	} ) ),
	// Note: technically we support all types of charts that `react-google-charts`
	// supports, which is _all_ chart types from Google Charts. But we only list
	// the charts currently used in our codebase here, and only ones that we have
	// explicit support/styles/handling for.
	// See: https://github.com/google/site-kit-wp/pull/2916#discussion_r626620601
	chartType: PropTypes.oneOf( [
		'LineChart',
		'PieChart',
	] ).isRequired,
	data: PropTypes.arrayOf(
		PropTypes.oneOfType( [
			PropTypes.arrayOf( PropTypes.object ),
			PropTypes.object,
		] ),
	),
	getChartWrapper: PropTypes.func,
	height: PropTypes.string,
	loaded: PropTypes.bool,
	loadingHeight: PropTypes.string,
	loadingWidth: PropTypes.string,
	onMouseOut: PropTypes.func,
	onMouseOver: PropTypes.func,
	onReady: PropTypes.func,
	onSelect: PropTypes.func,
	selectedStats: PropTypes.arrayOf( PropTypes.number ),
	width: PropTypes.string,
};

GoogleChart.defaultProps = {
	...Chart.defaultProps,
	loaded: true,
};
<commit_msg>Use array as data type.<commit_after>/**
 * GoogleChart component.
 *
 * Site Kit by Google, Copyright 2021 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/* eslint-disable react-hooks/exhaustive-deps */

/**
 * External dependencies
 */
import classnames from 'classnames';
import PropTypes from 'prop-types';
import { Chart } from 'react-google-charts';

/**
 * WordPress dependencies
 */
import { useEffect, useLayoutEffect, useRef } from '@wordpress/element';

/**
 * Internal dependencies
 */
import PreviewBlock from './PreviewBlock';

export default function GoogleChart( props ) {
	const {
		chartEvents,
		chartType,
		children,
		className,
		data,
		getChartWrapper,
		height,
		loaded,
		loadingHeight,
		loadingWidth,
		onMouseOver,
		onMouseOut,
		onReady,
		onSelect,
		selectedStats,
		width,
		...otherProps
	} = props;

	// Ensure we don't filter out columns that aren't data, but are things like
	// tooltips or other content.
	let nonDataColumns = [];
	if ( data?.length ) {
		nonDataColumns = data[ 0 ].reduce( ( acc, row, rowIndex ) => {
			return row?.role ? [ ...acc, rowIndex ] : acc;
		}, [] );
	}

	// If only certain columns should be displayed for the data set we have
	// then filter out that data.
	let modifiedData = data;
	if ( selectedStats?.length > 0 ) {
		modifiedData = data.map( ( row ) => {
			return row.filter( ( _columnValue, columnIndex ) => {
				return columnIndex === 0 || selectedStats.includes( columnIndex - 1 ) || nonDataColumns.includes( columnIndex - 1 );
			} );
		} );
	}

	let loadingHeightToUse = loadingHeight || height;
	let loadingWidthToUse = loadingWidth || width;
	// If a loading height is set but a width is not (or a loading width is set
	// but not a height), change the "unset" value to 100% to avoid visual bugs.
	// See: https://github.com/google/site-kit-wp/pull/2916#discussion_r623866269
	if ( loadingHeightToUse && ! loadingWidthToUse ) {
		loadingWidthToUse = '100%';
	}
	if ( loadingWidthToUse && ! loadingHeightToUse ) {
		loadingHeightToUse = '100%';
	}
	const loadingShape = chartType === 'PieChart' ? 'circular' : 'square';

	const loader = (

			<PreviewBlock
				className="googlesitekit-chart-loading__wrapper"
				height={ loadingHeightToUse }
				shape={ loadingShape }
				width={ loadingWidthToUse }
			/>

	);

	const chartWrapperRef = useRef();
	const googleRef = useRef();

	useEffect( () => {
		// Remove all event listeners after the component has unmounted.
		return () => {
			// eslint-disable-next-line no-unused-expressions
			if ( googleRef.current && chartWrapperRef.current ) {
				const { events } = googleRef.current.visualization;
				events.removeAllListeners( chartWrapperRef.current.getChart() );
				events.removeAllListeners( chartWrapperRef.current );
			}
		};
	}, [] );

	// These event listeners are added manually to the current chart because
	// `react-google-charts` doesn't support `mouseOver` or `mouseOut` events
	// in its `chartEvents` prop.
	// See: https://github.com/google/site-kit-wp/pull/2805#discussion_r579172660
	useLayoutEffect( () => {
		if ( onMouseOver ) {
			// eslint-disable-next-line no-unused-expressions
			googleRef.current?.visualization.events.addListener( chartWrapperRef.current.getChart(), 'onmouseover', ( event ) => {
				onMouseOver( event, {
					chartWrapper: chartWrapperRef.current,
					google: googleRef.current,
				} );
			} );
		}

		if ( onMouseOut ) {
			// eslint-disable-next-line no-unused-expressions
			googleRef.current?.visualization.events.addListener( chartWrapperRef.current.getChart(), 'onmouseout', ( event ) => {
				onMouseOut( event, {
					chartWrapper: chartWrapperRef.current,
					google: googleRef.current,
				} );
			} );
		}
	}, [ onMouseOver, onMouseOut ] );

	if ( ! loaded ) {
		return (

				{ loader }

		);
	}

	const combinedChartEvents = [ ...chartEvents || [] ];

	if ( onReady ) {
		combinedChartEvents.push( {
			eventName: 'ready',
			callback: onReady,
		} );
	}

	if ( onSelect ) {
		combinedChartEvents.push( {
			eventName: 'select',
			callback: onSelect,
		} );
	}

	return (
		<div
			className={ classnames(
				'googlesitekit-chart',
				`googlesitekit-chart--${ chartType }`,
				className
			) }
		>
			<Chart
				className="googlesitekit-chart__inner"
				chartEvents={ combinedChartEvents }
				chartType={ chartType }
				chartVersion="49"
				data={ modifiedData }
				loader={ loader }
				height={ height }
				getChartWrapper={ ( chartWrapper, google ) => {
					// Remove all the event listeners on the old chart before we draw
					// a new one. Only run this if the old chart and the new chart aren't
					// the same reference though, otherwise we'll remove existing `onReady`
					// events and other event listeners, which will cause bugs.
					if ( chartWrapper !== chartWrapperRef.current ) {
						// eslint-disable-next-line no-unused-expressions
						googleRef.current?.visualization.events.removeAllListeners( chartWrapperRef.current?.getChart() );
						// eslint-disable-next-line no-unused-expressions
						googleRef.current?.visualization.events.removeAllListeners( chartWrapperRef.current );
					}

					chartWrapperRef.current = chartWrapper;
					googleRef.current = google;

					if ( getChartWrapper ) {
						getChartWrapper( chartWrapper, google );
					}
				} }
				width={ width }
				{ ...otherProps }
			/>
			{ children }

	);
}

GoogleChart.propTypes = {
	className: PropTypes.string,
	children: PropTypes.node,
	chartEvents: PropTypes.arrayOf( PropTypes.shape( {
		eventName: PropTypes.string,
		callback: PropTypes.func,
	} ) ),
	// Note: technically we support all types of charts that `react-google-charts`
	// supports, which is _all_ chart types from Google Charts. But we only list
	// the charts currently used in our codebase here, and only ones that we have
	// explicit support/styles/handling for.
	// See: https://github.com/google/site-kit-wp/pull/2916#discussion_r626620601
	chartType: PropTypes.oneOf( [
		'LineChart',
		'PieChart',
	] ).isRequired,
	data: PropTypes.array,
	getChartWrapper: PropTypes.func,
	height: PropTypes.string,
	loaded: PropTypes.bool,
	loadingHeight: PropTypes.string,
	loadingWidth: PropTypes.string,
	onMouseOut: PropTypes.func,
	onMouseOver: PropTypes.func,
	onReady: PropTypes.func,
	onSelect: PropTypes.func,
	selectedStats: PropTypes.arrayOf( PropTypes.number ),
	width: PropTypes.string,
};

GoogleChart.defaultProps = {
	...Chart.defaultProps,
	loaded: true,
};
<|endoftext|>


<commit_before>/*
 * This object's keys are (semver) version numbers, and the
 * values are arrays of objects each with a "selectors"
 * array and a "message" string.
 */
const versionDeprecations = {
  '14.0.0': [
    {
      selectors: ['.flex-item-equal', '.flex-sm-item-equal', '.flex-md-item-equal', '.flex-lg-item-equal', '.flex-xl-item-equal'],
      message: `This variable is deprecated. Use "flex-1" instead.`
    },
    {
      selectors: ['.UnderlineNav-item.selected', '.UnderlineNav-item.selected .UnderlineNav-octicon'],
      message: `Please use aria-selected="true" to indicate the selected state of an UnderlineNav item.`
    },
    {
      variables: ['$status-pending'],
      message: `This variable is deprecated.`
    },
    {
      variables: ['$highlight-yellow'],
      message: `This variable is deprecated.`
    },
    {
      variables: ['$repo-private-text', '$repo-private-bg', '$repo-private-icon'],
      message: `These variables are deprecated.`
    },
    {
      variables: ['$marketingSpacers', '$allSpacers'],
      message: `Please use the $marketing-spacers and $marketing-all-spacers variables.`
    },
    {
      variables: ['$exploregrid-item-border-radius'],
      message: `This variable is deprecated. Use "4px" instead.`
    },
    {
      variables: ['$stats-switcher-py', '$stats-viewport-height'],
      message: `These variables are deprecated.`
    },
    {
      variables: ['$min_tab_size', '$max_tab_size'],
      message: `These variables are deprecated.`
    }
  ],
  '13.0.0': [
    {
      selectors: [
        '.btn-purple',
        '.btn-purple:focus',
        '.btn-purple.focus',
        '.btn-purple:hover',
        '.btn-purple.hover',
        '.btn-purple:active',
        '.btn-purple.selected',
        '[open]>.btn-purple',
        '.btn-purple:disabled',
        '.btn-purple.disabled',
        '.btn-purple .Counter'
      ],
      message: `Please don't make purple buttons.`
    },
    {
      selectors: ['.text-pending'],
      message: `Please use the "text-yellow" class instead of "text-pending".`
    },
    {
      selectors: ['.bg-pending'],
      message: `Please use the "bg-yellow-dark" class instead of "bg-pending".`
    },
    {
      selectors: [
        '.container',
        '.container::before',
        '.container::after',
        '.columns',
        '.columns::before',
        '.columns::after',
        '.column',
        '.one-third',
        '.two-thirds',
        '.one-fourth',
        '.one-half',
        '.three-fourths',
        '.one-fifth',
        '.four-fifths'
      ],
      message: `Please use [grid classes](https://primer.style/css/objects/grid).`
    },
    {
      selectors: ['.centered'],
      message: `You can use the "mx-auto" class to center any element.`
    },
    {
      selectors: [
        '.dropdown-menu-content',
        '.dropdown.active .dropdown-menu-content',
        '.dropdown-menu-content.anim-scale-in'
      ],
      message: `The "dropdown-menu-content" class is unnecessary.`
    }
  ]
}

const {version: CURRENT_VERSION} = require('./package.json')
const semver = require('semver')

// map selectors to the version and message of their deprecation
const selectorDeprecations = new Map()
const variableDeprecations = new Map()
for (const [version, deps] of Object.entries(versionDeprecations)) {
  for (const {selectors = [], variables = [], message} of deps) {
    for (const selector of selectors) {
      selectorDeprecations.set(selector, {version, message})
    }
    for (const variable of variables) {
      variableDeprecations.set(variable, {version, message})
    }
  }
}

function isSelectorDeprecated(selector, version = CURRENT_VERSION) {
  const deprecation = selectorDeprecations.get(selector)
  return deprecation ? semver.gte(deprecation.version, version) : false
}

function isVariableDeprecated(variable, version = CURRENT_VERSION) {
  const deprecation = variableDeprecations.get(variable)
  return deprecation ? semver.gte(deprecation.version, version) : false
}

module.exports = {
  versionDeprecations,
  selectorDeprecations,
  variableDeprecations,
  isSelectorDeprecated,
  isVariableDeprecated
}
<commit_msg>Make it prettier<commit_after>/*
 * This object's keys are (semver) version numbers, and the
 * values are arrays of objects each with a "selectors"
 * array and a "message" string.
 */
const versionDeprecations = {
  '14.0.0': [
    {
      selectors: [
        '.flex-item-equal',
        '.flex-sm-item-equal',
        '.flex-md-item-equal',
        '.flex-lg-item-equal',
        '.flex-xl-item-equal'
      ],
      message: `This variable is deprecated. Use "flex-1" instead.`
    },
    {
      selectors: ['.UnderlineNav-item.selected', '.UnderlineNav-item.selected .UnderlineNav-octicon'],
      message: `Please use aria-selected="true" to indicate the selected state of an UnderlineNav item.`
    },
    {
      variables: ['$status-pending'],
      message: `This variable is deprecated.`
    },
    {
      variables: ['$highlight-yellow'],
      message: `This variable is deprecated.`
    },
    {
      variables: ['$repo-private-text', '$repo-private-bg', '$repo-private-icon'],
      message: `These variables are deprecated.`
    },
    {
      variables: ['$marketingSpacers', '$allSpacers'],
      message: `Please use the $marketing-spacers and $marketing-all-spacers variables.`
    },
    {
      variables: ['$exploregrid-item-border-radius'],
      message: `This variable is deprecated. Use "4px" instead.`
    },
    {
      variables: ['$stats-switcher-py', '$stats-viewport-height'],
      message: `These variables are deprecated.`
    },
    {
      variables: ['$min_tab_size', '$max_tab_size'],
      message: `These variables are deprecated.`
    }
  ],
  '13.0.0': [
    {
      selectors: [
        '.btn-purple',
        '.btn-purple:focus',
        '.btn-purple.focus',
        '.btn-purple:hover',
        '.btn-purple.hover',
        '.btn-purple:active',
        '.btn-purple.selected',
        '[open]>.btn-purple',
        '.btn-purple:disabled',
        '.btn-purple.disabled',
        '.btn-purple .Counter'
      ],
      message: `Please don't make purple buttons.`
    },
    {
      selectors: ['.text-pending'],
      message: `Please use the "text-yellow" class instead of "text-pending".`
    },
    {
      selectors: ['.bg-pending'],
      message: `Please use the "bg-yellow-dark" class instead of "bg-pending".`
    },
    {
      selectors: [
        '.container',
        '.container::before',
        '.container::after',
        '.columns',
        '.columns::before',
        '.columns::after',
        '.column',
        '.one-third',
        '.two-thirds',
        '.one-fourth',
        '.one-half',
        '.three-fourths',
        '.one-fifth',
        '.four-fifths'
      ],
      message: `Please use [grid classes](https://primer.style/css/objects/grid).`
    },
    {
      selectors: ['.centered'],
      message: `You can use the "mx-auto" class to center any element.`
    },
    {
      selectors: [
        '.dropdown-menu-content',
        '.dropdown.active .dropdown-menu-content',
        '.dropdown-menu-content.anim-scale-in'
      ],
      message: `The "dropdown-menu-content" class is unnecessary.`
    }
  ]
}

const {version: CURRENT_VERSION} = require('./package.json')
const semver = require('semver')

// map selectors to the version and message of their deprecation
const selectorDeprecations = new Map()
const variableDeprecations = new Map()
for (const [version, deps] of Object.entries(versionDeprecations)) {
  for (const {selectors = [], variables = [], message} of deps) {
    for (const selector of selectors) {
      selectorDeprecations.set(selector, {version, message})
    }
    for (const variable of variables) {
      variableDeprecations.set(variable, {version, message})
    }
  }
}

function isSelectorDeprecated(selector, version = CURRENT_VERSION) {
  const deprecation = selectorDeprecations.get(selector)
  return deprecation ? semver.gte(deprecation.version, version) : false
}

function isVariableDeprecated(variable, version = CURRENT_VERSION) {
  const deprecation = variableDeprecations.get(variable)
  return deprecation ? semver.gte(deprecation.version, version) : false
}

module.exports = {
  versionDeprecations,
  selectorDeprecations,
  variableDeprecations,
  isSelectorDeprecated,
  isVariableDeprecated
}
<|endoftext|>