(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){ module.exports = { server_url: `${location.origin}${ location.origin.charAt(location.origin.length - 1) !== "/" ? "/" : "" }`, in_construction: true, }; },{}],2:[function(require,module,exports){ const { server_url } = require("./config"); module.exports = { images_url: `${server_url}assets/images`, news_articles_url: `${server_url}news-articles`, game_articles_url: `${server_url}game-articles`, software_articles_url: `${server_url}software-articles`, }; },{"./config":1}],3:[function(require,module,exports){ "use strict"; const objectHtmlRenderer = require("../lib/object-html-renderer"); class ImageCarousel { constructor(props) { this.props = props; this.id = performance.now(); this.state = { showImageIndex: 0, }; this.RUN_INTERVAL = 5000; this.props.images.length > 1 && 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", alt: `image carousel ${images[showImageIndex].replace(/\.[A-Za-z]+/, "")}`, 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 { constructor() { this.id = performance.now().toString(); this.state = { loading: true, articles: [], showArticleIndex: -1, }; this.loadArticles(); } loadArticles() { loadArticles(news_articles_url).then(articles => { this.state.articles = articles; this.state.showArticleIndex = this.state.articles.length - 1; this.refresh(); }); } refresh() { objectHtmlRenderer.subRender(this.render(), document.getElementById(this.id), { mode: "replace", }); } renderArticle(articleData) { return { tag: "article", contents: [ { tag: "div", class: "date", contents: [{ tag: "span", contents: getArticleDate(articleData.date) }], }, { 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", contents: getArticleBody(articleData.body), }, ], }, new ImageCarousel({ images: articleData.images.map(img => `${articleData.path}/images/${img}`), }).render(), ], }; } renderArticlePlaceholder() { return { tag: "article", class: "article-placeholder", contents: [ { tag: "div", class: "date" }, { tag: "div", class: "title" }, { tag: "div", class: "subtitle" }, { tag: "div", class: "body" }, { tag: "div", class: "image-carousel" }, ], }; } 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]), { 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"), }, ], }, ] : [this.renderArticlePlaceholder()], }; } } module.exports = NewsArticles; },{"../../constants":2,"../generic-components/image-carousel":3,"../lib/article-utils":7,"../lib/object-html-renderer":9}],5:[function(require,module,exports){ "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", alt:`thematic image ${this.props.img.replace(/\.[A-Za-z]+/, "")}`,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"; const { images_url } = require("../constants"); const NewsArticles = require("./home-page-components/news-articles"); const ThemeCard = require("./home-page-components/theme-card"); class HomePage { constructor(args) { Object.assign(this, args); } render() { return { tag: "div", id: "home-page", contents: [ { tag: "div", class: "page-header", contents: [ { tag: "div", class: "big-logo page-contents-center", contents: [ { tag: "img", alt: "logo Kuadrado", src: `${images_url}/logo_kuadrado.svg`, }, { tag: "img", class: "logo-text", alt: "Kuadrado", src: `${images_url}/logo_kuadrado_txt.svg`, }, ], }, { 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. <br/>Nous avons choisi ce symbole pour revendiquer le fait d'aimer fabriquer les choses nous-même ... Quitte parfois à réinventer un peu la roue ! `, }, ], }, { tag: "section", class: "page-contents-center", contents: [ { tag: "h2", contents: "Actu", class: "section-title bg-blue" }, new NewsArticles().render(), ], }, { tag: "div", class: "page-philo", contents: [ { tag: "p", class: "page-contents-center", contents: `Nous avons à cœur une démarche de légèreté et de simplicité dans nos créations. <br /><br />Nous travaillons pour le plaisir de créer, de maîtriser et de comprendre.`, }, ], }, { tag: "section", class: "page-contents-center grid-3", contents: [ { title: "Jeux", img: "game_controller.svg", 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", img: "meca_proc.svg", href: "/software-development/", description: `Quand nous avons besoin d'un outil numérique, développement web, moteur de jeux ou outillage logiciel, nous aimons bien le fabriquer nous-même si c'est possible ... et si ça nous amuse ! <br/>Retrouvez nos projets software en détail sur cette page.`, }, { title: "Pédagogie", img: "brain.svg", href: "/education/", description: `Démystifier et s'approprier la technologie par le partage de connaissances. <br/>Découvrez nos initiatives pédagogiques.`, }, ].map(cardProps => new ThemeCard(cardProps).render()), }, ], }; } } module.exports = HomePage; },{"../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.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( json.articles.map(async articlePath => { 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){ "use strict"; function fetchjson(url) { return new Promise((resolve, reject) => { fetch(url) .then(r => r.json()) .then(r => resolve(r)) .catch(e => reject(e)); }); } function fetchtext(url) { return new Promise((resolve, reject) => { fetch(url) .then(r => r.text()) .then(r => resolve(r)) .catch(e => reject(e)); }); } module.exports = { fetchjson, fetchtext, }; },{}],9:[function(require,module,exports){ "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; } }, }; },{}],10:[function(require,module,exports){ "use strict"; const HomePage = require("./homepage"); const runPage = require("./run-page"); runPage(HomePage); },{"./homepage":6,"./run-page":11}],11:[function(require,module,exports){ "use strict"; const objectHtmlRenderer = require("./lib/object-html-renderer"); const Template = require("./template/template"); module.exports = function runPage(PageComponent) { const template = new Template({ page: new PageComponent() }); objectHtmlRenderer.setRenderCycleRoot(template); objectHtmlRenderer.renderCycle(); }; },{"./lib/object-html-renderer":9,"./template/template":13}],12:[function(require,module,exports){ "use strict"; const { images_url } = require("../../../constants"); const NAV_MENU_ITEMS = [ ["/games/", "Jeux"], ["/software-development/", "Software"], [ "/education/", "Pédagogie", [ // submenu ["/education/#game-studio-club", "Game Studio Club"], ["/education/#popularization", "Vulgarisation numérique"], ], ], ]; 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", href: "/", contents: [ { tag: "img", alt: "Logo Kuadrado", src: `${images_url}/logo_kuadrado.svg`, }, { tag: "img", alt: "Kuadrado Software", class: "logo-text", src: `${images_url}/logo_kuadrado_txt.svg`, }, ], }, ], }; } renderMenu(menuItemsArray, isSubmenu = false) { return { tag: "ul", id: "nav-menu-list", class: isSubmenu ? "submenu" : "", contents: menuItemsArray.map(link => { const [href, text, submenu] = link; return { tag: "li", class: !isSubmenu && window.location.pathname === href ? "active" : "", contents: [ { tag: "a", href, contents: text, }, ].concat(submenu ? [this.renderMenu(submenu, true)] : []), }; }), }; } renderResponsiveBurger() { return { tag: "div", class: "burger", onclick: this.handleBurgerClick.bind(this), contents: [{ tag: "span", contents: "···" }], }; } render() { return { tag: "nav", contents: [ this.renderHome(), this.renderResponsiveBurger(), this.renderMenu(NAV_MENU_ITEMS), ], }; } } module.exports = NavBar; },{"../../../constants":2}],13:[function(require,module,exports){ "use strict"; const { in_construction } = require("../../config"); const { images_url } = require("../../constants"); const NavBar = require("./components/navbar"); class Template { constructor(props) { this.props = props; } render() { return { tag: "main", contents: [ { tag: "header", contents: [new NavBar().render()], }, in_construction && { tag: "section", class: "warning-banner", contents: [ { tag: "strong", class: "page-contents-center", contents: "Site en construction ...", }, ], }, { tag: "section", id: "page-container", contents: [this.props.page.render()], }, { tag: "footer", contents: [ { tag: "div", class: "logo", contents: [ { tag: "img", alt: `logo Kuadrado`, src: `${images_url}/logo_kuadrado.svg`, }, { tag: "img", class: "text-logo", alt: "Kuadrado Software", src: `${images_url}/logo_kuadrado_txt.svg`, }, ], }, { 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.", }, { tag: "a", href: "mailto:contact@kuadrado-software.fr", contents: "contact@kuadrado-software.fr", }, ], }, ], }; } } module.exports = Template; },{"../../config":1,"../../constants":2,"./components/navbar":12}]},{},[10]);