Pour tout problème contactez-nous par mail : support@froggit.fr | La FAQ :grey_question: | Rejoignez-nous sur le Chat :speech_balloon:

Skip to content
Snippets Groups Projects
main.js 24.8 KiB
Newer Older
peter_rabbit's avatar
peter_rabbit committed
(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
peter_rabbit's avatar
peter_rabbit committed
module.exports = {
    server_url: `${location.origin}${
        location.origin.charAt(location.origin.length - 1) !== "/" ? "/" : ""
    }`,
    in_construction: true,
};
peter_rabbit's avatar
peter_rabbit committed

},{}],2:[function(require,module,exports){
const { server_url } = require("./config");

module.exports = {
    images_url: `${server_url}/assets/images`,
peter_rabbit's avatar
peter_rabbit committed
    news_articles_url: `${server_url}/news-articles`,
    game_articles_url: `${server_url}/game-articles`,
    software_articles_url: `${server_url}/software-articles`,
peter_rabbit's avatar
peter_rabbit committed
};

},{"./config":1}],3:[function(require,module,exports){
peter_rabbit's avatar
peter_rabbit committed
"use strict";

peter_rabbit's avatar
peter_rabbit committed
const objectHtmlRenderer = require("../lib/object-html-renderer");

peter_rabbit's avatar
peter_rabbit committed
class ImageCarousel {
    constructor(props) {
        this.props = props;
        this.id = performance.now();
        this.state = {
            showImageIndex: 0,
        };
        this.RUN_INTERVAL = 5000;
        this.run();
    }

    run() {
        this.runningInterval = setInterval(() => {
            let { showImageIndex } = this.state;
            const { images } = this.props;
            this.state.showImageIndex = showImageIndex < images.length - 1 ? ++showImageIndex : 0;
            this.refreshImage();
        }, this.RUN_INTERVAL);
    }

    setImageIndex(i) {
        clearInterval(this.runningInterval);
        this.state.showImageIndex = i;
        this.refreshImage();
    }

    refreshImage() {
        objectHtmlRenderer.subRender(this.render(), document.getElementById(this.id), {
            mode: "replace",
        });
    }

    render() {
        const { showImageIndex } = this.state;
        const { images } = this.props;
        return {
            tag: "div",
            id: this.id,
            class: "image-carousel",
            contents: [
                { tag: "img", src: images[showImageIndex] },
                images.length > 1 && {
                    tag: "div",
                    class: "carousel-bullets",
                    contents: images.map((_, i) => {
                        const active = showImageIndex === i;
                        return {
                            tag: "span",
                            class: `bullet ${active ? "active" : ""}`,
                            onclick: this.setImageIndex.bind(this, i),
                        };
                    }),
                },
            ],
        };
    }
}

module.exports = ImageCarousel;

},{"../lib/object-html-renderer":9}],4:[function(require,module,exports){
"use strict";

const { news_articles_url } = require("../../constants");
const objectHtmlRenderer = require("../lib/object-html-renderer");
const ImageCarousel = require("../generic-components/image-carousel");
const { loadArticles, getArticleDate, getArticleBody } = require("../lib/article-utils");

class NewsArticles {
peter_rabbit's avatar
peter_rabbit committed
    constructor() {
        this.id = performance.now().toString();
        this.state = {
            loading: true,
            articles: [],
            showArticleIndex: -1,
        };
        this.loadArticles();
    }

    loadArticles() {
peter_rabbit's avatar
peter_rabbit committed
        loadArticles(news_articles_url).then(articles => {
            this.state.articles = articles;
            this.state.showArticleIndex = this.state.articles.length - 1;
            this.refresh();
        });
peter_rabbit's avatar
peter_rabbit committed
    }

    refresh() {
        objectHtmlRenderer.subRender(this.render(), document.getElementById(this.id), {
            mode: "replace",
        });
    }

    renderArticle(articleData) {
        return {
            tag: "article",
            contents: [
                {
                    tag: "div",
                    class: "date",
peter_rabbit's avatar
peter_rabbit committed
                    contents: [{ tag: "span", contents: getArticleDate(articleData.date) }],
peter_rabbit's avatar
peter_rabbit committed
                },
                {
                    tag: "div",
                    class: "title",
                    contents: [
                        {
                            tag: "h3",
                            contents: articleData.title,
                        },
                    ],
                },
                {
                    tag: "div",
                    class: "subtitle",
                    contents: [
                        {
                            tag: "strong",
                            contents: articleData.subtitle,
                        },
                    ],
                },
                {
                    tag: "div",
                    class: "body",
                    contents: [
                        {
                            tag: "p",
peter_rabbit's avatar
peter_rabbit committed
                            contents: getArticleBody(articleData.body),
peter_rabbit's avatar
peter_rabbit committed
                        },
                    ],
                },
                new ImageCarousel({
                    images: articleData.images.map(img => `${articleData.path}/images/${img}`),
                }).render(),
            ],
        };
    }

    renderArticlePlaceholder() {
        return {
            tag: "article",
            class: "article-placeholder",
peter_rabbit's avatar
peter_rabbit committed
            contents: [
                { tag: "div", class: "date" },
                { tag: "div", class: "title" },
                { tag: "div", class: "subtitle" },
                { tag: "div", class: "body" },
                { tag: "div", class: "image-carousel" },
peter_rabbit's avatar
peter_rabbit committed
            ],
        };
    }

    handleChangeArticle(dir) {
        let { showArticleIndex, articles } = this.state;
        showArticleIndex =
            dir === "prev"
                ? showArticleIndex - 1 >= 0
                    ? showArticleIndex - 1
                    : 0
                : showArticleIndex + 1 <= articles.length - 1
                ? showArticleIndex + 1
                : articles.length - 1;
        this.state.showArticleIndex = showArticleIndex;
        this.refresh();
    }

    render() {
        const { articles, showArticleIndex } = this.state,
            showNext = showArticleIndex < articles.length - 1,
            showPrev = showArticleIndex > 0;
        return {
            tag: "div",
            id: this.id,
            class: "articles-displayer page-contents-center",
            contents:
                articles.length > 0
                    ? [
                          this.renderArticle(articles[showArticleIndex]),
                          {
peter_rabbit's avatar
peter_rabbit committed
                              tag: "div",
                              class: "prev-next-buttons",
                              contents: [
                                  {
                                      tag: "button",
                                      class: `prev-btn ${!showPrev ? "disabled" : "active"}`,
                                      contents: "Précédent",
                                      onclick: this.handleChangeArticle.bind(this, "prev"),
                                  },
                                  {
                                      tag: "button",
                                      class: `next-btn ${!showNext ? "disabled" : "active"}`,
                                      contents: "Suivant",
                                      onclick: this.handleChangeArticle.bind(this, "next"),
                                  },
                              ],
peter_rabbit's avatar
peter_rabbit committed
                          },
                      ]
peter_rabbit's avatar
peter_rabbit committed
                    : [this.renderArticlePlaceholder()],
peter_rabbit's avatar
peter_rabbit committed
module.exports = NewsArticles;
peter_rabbit's avatar
peter_rabbit committed

peter_rabbit's avatar
peter_rabbit committed
},{"../../constants":2,"../generic-components/image-carousel":3,"../lib/article-utils":7,"../lib/object-html-renderer":9}],5:[function(require,module,exports){
peter_rabbit's avatar
peter_rabbit committed
"use strict";

const { images_url } = require("../../constants");

class ThemeCard {
    constructor(props) {
        this.props = props;
    }

    render() {
        return {
            tag: "a",
            class: "theme-card",
            href: this.props.href,
            contents: [
                {
                    tag: "div",
                    class: "card-img",
                    contents: [{ tag: "img", src: `${images_url}/${this.props.img}` }],
                },
                {
                    tag: "div",
                    class: "card-title",
                    contents: [{ tag: "h2", class: "section-title", contents: this.props.title }],
                },
                {
                    tag: "div",
                    class: "card-description",
                    contents: [{ tag: "p", contents: this.props.description }],
                },
            ],
        };
    }
}

module.exports = ThemeCard;

},{"../../constants":2}],6:[function(require,module,exports){
"use strict";

peter_rabbit's avatar
peter_rabbit committed
const { images_url } = require("../constants");
const NewsArticles = require("./home-page-components/news-articles");
peter_rabbit's avatar
peter_rabbit committed
const ThemeCard = require("./home-page-components/theme-card");

peter_rabbit's avatar
peter_rabbit committed
class HomePage {
    constructor(args) {
        Object.assign(this, args);
    }

    render() {
        return {
peter_rabbit's avatar
peter_rabbit committed
            tag: "div",
peter_rabbit's avatar
peter_rabbit committed
            id: "home-page",
peter_rabbit's avatar
peter_rabbit committed
            contents: [
                {
peter_rabbit's avatar
peter_rabbit committed
                    tag: "div",
                    class: "page-header",
                    contents: [
peter_rabbit's avatar
peter_rabbit committed
                        {
                            tag: "div",
                            class: "big-logo page-contents-center",
                            contents: [
                                { tag: "img", src: `${images_url}/logo_kuadrado.svg` },
                                {
                                    tag: "img",
                                    class: "logo-text",
                                    src: `${images_url}/logo_kuadrado_txt.svg`,
                                },
                            ],
                        },
peter_rabbit's avatar
peter_rabbit committed
                        { tag: "h1", contents: "Kuadrado Software", class: "page-contents-center" },
                        {
                            tag: "p",
                            class: "page-contents-center",
                            contents: `<b>Kvadrata rado</b> veut dire "roue carrée" en Esperanto, c'est le symbole que nous avons choisi pour Kuadrado 
                            pour dire qu'on aime bien fabriquer les trucs nous même, avec des briques aussi élémentaires que possible, 
                            pour le plaisir de les maîtriser et de les comprendre. Quitte parfois à réinventer un peu la roue.
                            `,
                        },
                    ],
                },
                {
                    tag: "section",
                    class: "page-contents-center",
                    contents: [
                        { tag: "h2", contents: "Actu", class: "section-title bg-blue" },
peter_rabbit's avatar
peter_rabbit committed
                        new NewsArticles().render(),
peter_rabbit's avatar
peter_rabbit committed
                    ],
                },
peter_rabbit's avatar
peter_rabbit committed
                {
                    tag: "div",
                    class: "page-philo",
                    contents: [
                        {
                            tag: "p",
                            class: "page-contents-center",
                            contents: `Nous sommes engagés dans un idéal de légèreté et de simplicité dans nos créations qu'elle soient artistiques ou logicielles.
                            <br /><br />Nous voulons travailler pour le plaisir de créer et de maîtriser ce qu'on fait.`,
                        },
                    ],
                },
peter_rabbit's avatar
peter_rabbit committed
                {
                    tag: "section",
                    class: "page-contents-center grid-3",
                    contents: [
                        {
                            title: "Jeux",
peter_rabbit's avatar
peter_rabbit committed
                            img: "game_controller.svg",
peter_rabbit's avatar
peter_rabbit committed
                            href: "/games/",
                            description:
                                "Toutes nos créations vidéoludiques, jeux web et jeux PC, projets en cours, c'est par ici que ça se passe.",
                        },
                        {
                            title: "Software",
peter_rabbit's avatar
peter_rabbit committed
                            img: "meca_proc.svg",
peter_rabbit's avatar
peter_rabbit committed
                            href: "/software-development/",
                            description:
                                "Des fois quand on a besoin d'un outil, on le fabrique nous même (si ça nous amuse) ! Retrouvez les projets en détail.",
                        },
                        {
                            title: "Pédagogie",
                            img: "popularization_banner.png",
                            href: "/education/",
                            description:
                                "La pédagogie est une arme puissante pour faire tomber les barrières entre les gens et la technologie, et nous sommes bien décidés à en faire usage !",
                        },
                    ].map(cardProps => new ThemeCard(cardProps).render()),
peter_rabbit's avatar
peter_rabbit committed
                },
            ],
        };
    }
}

module.exports = HomePage;

peter_rabbit's avatar
peter_rabbit committed
},{"../constants":2,"./home-page-components/news-articles":4,"./home-page-components/theme-card":5}],7:[function(require,module,exports){
"use strict";

const { fetchjson, fetchtext } = require("./fetch");

function getArticleBody(text) {
    return text
        .split(" ")
        .map(word => {
            if (word.includes("http://") || word.includes("https://")) {
                const splitword = word.split("||");
                const href = splitword[0].match(/http.+/);
                const text = splitword.length > 1 ? splitword[1].replaceAll("_", " ") : href;
                return word.replace(/http.*/, `<a href=${href} target="_blank">${text}</a>`);
            } else return word;
        })
        .join(" ")
        .replaceAll("\n", "<br/>");
}

function getArticleDate(date) {
    return `${date.getDate()}-${date.getMonth() + 1}-${date.getFullYear()}`;
}

function loadArticles(dir_url) {
    return new Promise((resolve, reject) => {
        fetchjson(`${dir_url}/index.json`)
            .then(json => {
                Promise.all(
peter_rabbit's avatar
peter_rabbit committed
                    json.articles.map(async articlePath => {
peter_rabbit's avatar
peter_rabbit committed
                        const art = await fetchjson(`${dir_url}/${articlePath}`);
                        const tmpSplit = articlePath.split("/");
                        tmpSplit.pop();
                        const absArtPath = `${dir_url}/${tmpSplit.join("/")}`;
                        return Object.assign(art, { path: absArtPath });
                    })
                )
                    .then(articles => {
                        populateArticles(articles)
                            .then(completeArticles => resolve(completeArticles))
                            .catch(e => reject(e));
                    })
                    .catch(e => reject(e));
            })
            .catch(e => console.log(e));
    });
}

function populateArticles(articles) {
    return new Promise((resolve, reject) => {
        Promise.all(
            articles.map(async article => {
                if (article.body.indexOf("<file>") !== -1) {
                    const txtPath = article.body.replace("<file>", "");
                    const textValue = await fetchtext(`${article.path}/${txtPath}`);
                    article.body = textValue;
                    article.date = article.date ? new Date(article.date) : undefined;
                }
                return article;
            })
        )
            .then(completeArticles => resolve(completeArticles.sort((a, b) => a.date - b.date)))
            .catch(e => reject(e));
    });
}

module.exports = {
    loadArticles,
    getArticleBody,
    getArticleDate,
    populateArticles,
};

},{"./fetch":8}],8:[function(require,module,exports){
peter_rabbit's avatar
peter_rabbit committed
"use strict";

function fetchjson(url) {
    return new Promise((resolve, reject) => {
        fetch(url)
peter_rabbit's avatar
peter_rabbit committed
            .then(r => r.json())
            .then(r => resolve(r))
            .catch(e => reject(e));
    });
peter_rabbit's avatar
peter_rabbit committed
}
peter_rabbit's avatar
peter_rabbit committed

function fetchtext(url) {
    return new Promise((resolve, reject) => {
        fetch(url)
peter_rabbit's avatar
peter_rabbit committed
            .then(r => r.text())
            .then(r => resolve(r))
            .catch(e => reject(e));
    });
peter_rabbit's avatar
peter_rabbit committed
}
peter_rabbit's avatar
peter_rabbit committed

module.exports = {
peter_rabbit's avatar
peter_rabbit committed
    fetchjson,
    fetchtext,
};
peter_rabbit's avatar
peter_rabbit committed

peter_rabbit's avatar
peter_rabbit committed
},{}],9:[function(require,module,exports){
peter_rabbit's avatar
peter_rabbit committed
"use strict";

module.exports = {
    setRenderCycleRoot(renderCycleRoot) {
        this.renderCycleRoot = renderCycleRoot;
    },
    objectToHtml: function objectToHtml(obj) {
        const { tag } = obj;

        const node = document.createElement(tag);
        const excludeKeys = ["tag", "contents", "style_rules", "state"];

        Object.keys(obj)
            .filter(attr => !excludeKeys.includes(attr))
            .forEach(attr => {
                if (attr === "class") {
                    node.classList.add(...obj[attr].split(" ").filter(s => s !== ""));
                } else {
                    node[attr] = obj[attr];
                }
            });
        if (obj.contents && typeof obj.contents === "string") {
            node.innerHTML = obj.contents;
        } else {
            obj.contents &&
                obj.contents.length > 0 &&
                obj.contents.forEach(el => {
                    switch (typeof el) {
                        case "string":
                            node.innerHTML = el;
                            break;
                        case "object":
                            node.appendChild(objectToHtml(el));
                            break;
                    }
                });
        }

        if (obj.style_rules) {
            Object.keys(obj.style_rules).forEach(rule => {
                node.style[rule] = obj.style_rules[rule];
            });
        }

        return node;
    },
    renderCycle: function () {
        this.subRender(this.renderCycleRoot.render(), document.getElementsByTagName("main")[0], {
            mode: "replace",
        });
    },
    subRender(object, htmlNode, options = { mode: "append" }) {
        const insert = this.objectToHtml(object);
        switch (options.mode) {
            case "append":
                htmlNode.appendChild(insert);
                break;
            case "override":
                htmlNode.innerHTML = "";
                htmlNode.appendChild(insert);
                break;
            case "insert-before":
                htmlNode.insertBefore(insert, htmlNode.childNodes[options.insertIndex]);
                break;
            case "adjacent":
                /**
                 * options.insertLocation must be one of:
                 *
                 * afterbegin
                 * afterend
                 * beforebegin
                 * beforeend
                 */
                htmlNode.insertAdjacentHTML(options.insertLocation, insert);
                break;
            case "replace":
                htmlNode.parentNode.replaceChild(insert, htmlNode);
                break;
            case "remove":
                htmlNode.remove();
                break;
        }
    },
};

peter_rabbit's avatar
peter_rabbit committed
},{}],10:[function(require,module,exports){
peter_rabbit's avatar
peter_rabbit committed
"use strict";

const HomePage = require("./homepage");
const runPage = require("./run-page");

runPage(HomePage);

peter_rabbit's avatar
peter_rabbit committed
},{"./homepage":6,"./run-page":11}],11:[function(require,module,exports){
peter_rabbit's avatar
peter_rabbit committed
"use strict";

const objectHtmlRenderer = require("./lib/object-html-renderer");
peter_rabbit's avatar
peter_rabbit committed
const Template = require("./template/template");
peter_rabbit's avatar
peter_rabbit committed

module.exports = function runPage(PageComponent) {
peter_rabbit's avatar
peter_rabbit committed
    const template = new Template({ page: new PageComponent() });
    objectHtmlRenderer.setRenderCycleRoot(template);
peter_rabbit's avatar
peter_rabbit committed
    objectHtmlRenderer.renderCycle();
};

peter_rabbit's avatar
peter_rabbit committed
},{"./lib/object-html-renderer":9,"./template/template":13}],12:[function(require,module,exports){
peter_rabbit's avatar
peter_rabbit committed
"use strict";

const { images_url } = require("../../../constants");
peter_rabbit's avatar
peter_rabbit committed

peter_rabbit's avatar
peter_rabbit committed
const NAV_MENU_ITEMS = [
    ["/games/", "Jeux"],
    ["/software-development/", "Software"],
peter_rabbit's avatar
peter_rabbit committed
    [
        "/education/",
peter_rabbit's avatar
peter_rabbit committed
        "Pédagogie",
        [
            // submenu
            ["/education/#game-studio-club", "Game Studio Club"],
            ["/education/#popularization", "Vulgarisation numérique"],
peter_rabbit's avatar
peter_rabbit committed
        ],
    ],
];

class NavBar {
    constructor() {
        this.initEventHandlers();
    }

    handleBurgerClick() {
        document.getElementById("nav-menu-list").classList.toggle("responsive-show");
    }

    initEventHandlers() {
        window.addEventListener("click", event => {
            if (
                event.target.id !== "nav-menu-list" &&
                !event.target.classList.contains("burger") &&
                !event.target.parentNode.classList.contains("burger")
            ) {
                document.getElementById("nav-menu-list").classList.remove("responsive-show");
            }
        });
    }

    renderHome() {
        return {
            tag: "div",
            class: "home",
            contents: [
                {
                    tag: "a",
peter_rabbit's avatar
peter_rabbit committed
                        { tag: "img", src: `${images_url}/logo_kuadrado.svg` },
                        {
                            tag: "img",
                            class: "logo-text",
                            src: `${images_url}/logo_kuadrado_txt.svg`,
                        },
peter_rabbit's avatar
peter_rabbit committed
    renderMenu(menuItemsArray, isSubmenu = false) {
peter_rabbit's avatar
peter_rabbit committed
            tag: "ul",
            id: "nav-menu-list",
peter_rabbit's avatar
peter_rabbit committed
            class: isSubmenu ? "submenu" : "",
            contents: menuItemsArray.map(link => {
                const [href, text, submenu] = link;
peter_rabbit's avatar
peter_rabbit committed
                return {
                    tag: "li",
                    class: !isSubmenu && window.location.pathname === href ? "active" : "",
peter_rabbit's avatar
peter_rabbit committed
                    contents: [
                        {
                            tag: "a",
                            href,
peter_rabbit's avatar
peter_rabbit committed
                        },
                    ].concat(submenu ? [this.renderMenu(submenu, true)] : []),
peter_rabbit's avatar
peter_rabbit committed
                };
            }),
        };
    }

    renderResponsiveBurger() {
        return {
            tag: "div",
            class: "burger",
            onclick: this.handleBurgerClick.bind(this),
            contents: [{ tag: "span", contents: "···" }],
        };
peter_rabbit's avatar
peter_rabbit committed
    }

    render() {
        return {
            tag: "nav",
            contents: [
                this.renderHome(),
                this.renderResponsiveBurger(),
                this.renderMenu(NAV_MENU_ITEMS),
            ],
        };
    }
}

module.exports = NavBar;

peter_rabbit's avatar
peter_rabbit committed
},{"../../../constants":2}],13:[function(require,module,exports){
peter_rabbit's avatar
peter_rabbit committed
const { in_construction } = require("../../config");
peter_rabbit's avatar
peter_rabbit committed
const { images_url } = require("../../constants");
const NavBar = require("./components/navbar");

class Template {
    constructor(props) {
        this.props = props;
    }
peter_rabbit's avatar
peter_rabbit committed
    render() {
        return {
            tag: "main",
            contents: [
                {
                    tag: "header",
                    contents: [new NavBar().render()],
peter_rabbit's avatar
peter_rabbit committed
                },
peter_rabbit's avatar
peter_rabbit committed
                in_construction && {
                    tag: "section",
                    class: "warning-banner",
                    contents: [
                        {
                            tag: "strong",
                            class: "page-contents-center",
                            contents: "Site en construction ...",
                        },
                    ],
                },
peter_rabbit's avatar
peter_rabbit committed
                    tag: "section",
peter_rabbit's avatar
peter_rabbit committed
                    id: "page-container",
                    contents: [this.props.page.render()],
                },
                {
                    tag: "footer",
                    contents: [
peter_rabbit's avatar
peter_rabbit committed
                        {
                            tag: "div",
                            class: "logo",
                            contents: [
                                {
                                    tag: "img",
                                    src: `${images_url}/logo_kuadrado.svg`,
                                },
                                {
                                    tag: "img",
peter_rabbit's avatar
peter_rabbit committed
                                    class: "text-logo",
peter_rabbit's avatar
peter_rabbit committed
                                    src: `${images_url}/logo_kuadrado_txt.svg`,
                                },
                            ],
                        },
                        {
peter_rabbit's avatar
peter_rabbit committed
                            tag: "span",
                            contents:
                                "Toutes les images du site ont été réalisées par nos soins et peuvent être réutilisées pour un usage personnel.",
peter_rabbit's avatar
peter_rabbit committed
                        },
peter_rabbit's avatar
peter_rabbit committed
                        {
                            tag: "a",
peter_rabbit's avatar
peter_rabbit committed
                            href: "mailto:contact@kuadrado-software.fr",
                            contents: "contact@kuadrado-software.fr",
peter_rabbit's avatar
peter_rabbit committed
                        },
                    ],
                },
            ],
        };
    }
}

module.exports = Template;

peter_rabbit's avatar
peter_rabbit committed
},{"../../config":1,"../../constants":2,"./components/navbar":12}]},{},[10]);