// requires jquery 1.7+ // JS s'execute: Retire l'avertissement 'Javascript est requis' (de fait, on sait que JS est actif...) document.body.classList.remove("nojs"); //### Helpers handlebars personnalisés Handlebars.registerHelper('lower', function (options) { return options.fn(this).toLowerCase(); }); Handlebars.registerHelper('repuri', function (find, replace, options) { return encodeURI(options.fn(this).replace(find, replace).toString()); }); Handlebars.registerHelper('todate', function (options) { var d = options.fn(this); var dt = new Date(Number.parseInt(d) * 1); return dt.toLocaleString(); }); Handlebars.registerHelper('timestamp', function (options) { return Number.parseInt(options.fn(this)); }); Handlebars.registerHelper('if_eq', function (a, opts) { var b = localStorage.hasOwnProperty("contact") ? localStorage.getItem("contact") : ""; if (a === b) // Or === depending on your needs return opts.fn(this); else return opts.inverse(this); }); //### Initialisation var db_name = "MobiParc" var db_version = "3" var indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB || window.shimIndexedDB; var request; // Installe le service worker if ('serviceWorker' in navigator) { console.log("[ServiceWorker] Installe"); navigator.serviceWorker.register('../sw.js'); } var sectionId; var section; var load = function () { // Vide la section main $("#main").empty(); // Page en cours sectionId = (window.location.hash.slice(1).length > 0 ? window.location.hash.slice(1) : "index"); section = $("body").find('#' + sectionId); // compile la section avec handlebars if ($(section).attr("model")) { var model = $(section).attr("model"); var template = Handlebars.compile(section.html()); // Charge la base de données, et le stockage courant //var indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB || window.shimIndexedDB; request = indexedDB.open(db_name, db_version); var db; var txs; var store; // Cree les stockages necessaires si ceux ci sont manquants request.onupgradeneeded = function () { var db = request.result; db.createObjectStore(model, { keyPath: "guid" }); console.log("[DB] Cree '" + model + "'"); }; request.onsuccess = function () { db = request.result; txs = db.transaction(model, "readonly"); store = txs.objectStore(model); store.getAll().onsuccess = function (event) { var data = { data: event.target.result }; $("#main").html(template(data)); }; }; request.onerror = function () { console.log("Error while loading the db '" + model + "'"); $("#main").html(template({})); return; }; // Intercepte la soumision de formulaires $("#main").on("submit", "form", function (event) { console.log("handle submit"); var form = $("#main").find("form")[0]; // Stop the form from submitting since we’re handling that with AJAX. event.preventDefault(); // Call our function to get the form data. var data = formToJSON(form.elements); data.guid = createGuid(); //data.tstamp = Date.now(); data.user = localStorage.hasOwnProperty("params") ? JSON.parse(localStorage.getItem("params")).user : "(unknown)"; txs = db.transaction(model, "readwrite"); store = txs.objectStore(model); store.put(data); store.getAll().onsuccess = function (event) { $("#main").empty(); var data = { data: event.target.result }; var template = Handlebars.compile(section.html()); $("#main").html(template(data)); }; }); // Gere le clic sur un bouton supprimer $("body").on("click", ".del", function (event) { var del = $(this); if (confirm("Supprimer la selection!") == true) { $(del).prop("disabled", true); $(".ui-selected").each(function () { var elt = $(this); var id = $(elt).data("id"); //var datatype = $(elt).data("type"); txs = db.transaction(model, "readwrite"); store = txs.objectStore(model); store.delete(id).onsuccess = function (evt) { $(elt).remove(); }; }); } }); } else { //template = Handlebars.compile(section.html()); //$("#main").html(template({})); $("#main").html(section.html()); } } load(); // Recharge dynamiquement le contenu HTML à chaque changement d'url $(window).on('hashchange', function () { console.log("Trigger: hashchange"); load(); }); // ############ MAIN ############### // ### Interactions // Affiche ou masque la sidebar $('.bt-menu').on('click', 'svg', function () { $(this).closest('nav').find('div:not(:first)').toggleClass('sidebar'); }); $(document).on('click', '.sidebar', function () { $(this).closest('nav').find('div:not(:first)').toggleClass('sidebar'); }); // Affiche ou masque le bouton de sync if (navigator.onLine) { $(".data-sync").removeAttr("disabled"); } else { if (!$(".data-sync").is(":disabled")) { $(".data-sync").attr("disabled") } } /* retour haut de page*/ window.onscroll = function (ev) { document.getElementById("back-top").className =(window.pageYOffset > 100) ? "": "hidden"; }; $('#back-top').on('click', function () { $('html, body').animate({ scrollTop: 0 }, 200); }); // Gere l'affichage des classes modales $(".toggle-sync-dlg").click(function () { $(".modal-content,.modal-background").toggleClass("active"); if ($(this).hasClass("modal-close")) location.reload(); }); // Rend selectionables les lignes des tables (.selectable) $("#main").selectable({ filter: ".selectable tr", stop: function () { $(".del").removeAttr("disabled"); } }); // ### Synchronisation des données $(".data-sync").on("click", function () { if (!request) { request = indexedDB.open(db_name, db_version); request.onerror = function () { console.log("Error while accessing the db"); alert("Erreur: impossible d'accéder à la base de données locale."); return; }; } var db = request.result; var txs = db.transaction("activites", "readonly"); var stores = txs.objectStore("activites"); console.log("post all"); stores.openCursor().onsuccess = function (event) { var cursor = event.target.result; if (cursor) { cursor.value.model = "activites"; var id = cursor.value.guid; var posting = $.post("/api/mobiparc", { data: JSON.stringify(cursor.value) }); // Put the results in a div posting.done(function (data) { if (data == true) { var tx = db.transaction("activites", "readwrite"); var store = tx.objectStore("activites"); store.delete(id).onsuccess = function (evt) { $('.sync-result').append("Sync ok activite : " + id + "
"); }; } }); cursor.continue(); } else { console.log("end activite"); } }; }) //###### TOOLBOX ###### function createGuid() { return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c => (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16) ) } function getLocation() { try { if (navigator.geolocation) { navigator.geolocation.getCurrentPosition(showPosition); } else { console.log("Geolocation is not supported by this browser."); return 0; } } catch (e) { console.log("Geolocation: error"); } } function showPosition(position) { $("input[name='coordinates']").val(position.coords.latitude + "," + position.coords.longitude); console.log(position.coords); } // ### Serialization /** * Checks that an element has a non-empty `name` and `value` property. * @param {Element} element the element to check * @return {Bool} true if the element is an input, false if not */ var isValidElement = function isValidElement(element) { return element.name && element.value; }; /** * Checks if an element’s value can be saved (e.g. not an unselected checkbox). * @param {Element} element the element to check * @return {Boolean} true if the value should be added, false if not */ var isValidValue = function isValidValue(element) { return !['checkbox', 'radio'].includes(element.type) || element.checked; }; /** * Checks if an input is a checkbox, because checkboxes allow multiple values. * @param {Element} element the element to check * @return {Boolean} true if the element is a checkbox, false if not */ var isCheckbox = function isCheckbox(element) { return element.type === 'checkbox'; }; //var isHidden = function isHidden(element) { // return element.type === 'hidden'; //}; /** * Checks if an input is a `select` with the `multiple` attribute. * @param {Element} element the element to check * @return {Boolean} true if the element is a multiselect, false if not */ var isMultiSelect = function isMultiSelect(element) { return element.options && element.multiple; }; /** * Retrieves the selected options from a multi-select as an array. * @param {HTMLOptionsCollection} options the options for the select * @return {Array} an array of selected option values */ var getSelectValues = function getSelectValues(options) { return [].reduce.call(options, function (values, option) { return option.selected ? values.concat(option.value) : values; }, []); }; /** * A more verbose implementation of `formToJSON()` to explain how it works. * * NOTE: This function is unused, and is only here for the purpose of explaining how * reducing form elements works. * * @param {HTMLFormControlsCollection} elements the form elements * @return {Object} form data as an object literal */ var formToJSON_deconstructed = function formToJSON_deconstructed(elements) { // This is the function that is called on each element of the array. var reducerFunction = function reducerFunction(data, element) { // Add the current field to the object. data[element.name] = element.value; // For the demo only: show each step in the reducer’s progress. console.log(JSON.stringify(data)); return data; }; // This is used as the initial value of `data` in `reducerFunction()`. var reducerInitialValue = {}; // To help visualize what happens, log the inital value, which we know is `{}`. console.log('Initial `data` value:', JSON.stringify(reducerInitialValue)); // Now we reduce by `call`-ing `Array.prototype.reduce()` on `elements`. var formData = [].reduce.call(elements, reducerFunction, reducerInitialValue); // The result is then returned for use elsewhere. return formData; }; /** * Retrieves input data from a form and returns it as a JSON object. * @param {HTMLFormControlsCollection} elements the form elements * @return {Object} form data as an object literal */ var formToJSON = function formToJSON(elements) { return [].reduce.call(elements, function (data, element) { // Make sure the element has the required properties and should be added. if (isValidElement(element) && isValidValue(element)) { /* * Some fields allow for more than one value, so we need to check if this * is one of those fields and, if so, store the values as an array. */ if (isCheckbox(element)) { data[element.name] = (data[element.name] || []).concat(element.value); } else if (isMultiSelect(element)) { data[element.name] = getSelectValues(element); } else { data[element.name] = element.value; } } return data; }, {}); }; ///* // Intensify by TEMPLATED // templated.co @templatedco // Released for free under the Creative Commons Attribution 3.0 license (templated.co/license) //*/ //(function ($) { // skel.breakpoints({ // xlarge: '(max-width: 1680px)', // large: '(max-width: 1280px)', // medium: '(max-width: 980px)', // small: '(max-width: 736px)', // xsmall: '(max-width: 480px)' // }); // $(function () { // var $window = $(window), // $body = $('body'), // $header = $('#header'); // // Disable animations/transitions until the page has loaded. // $body.addClass('is-loading'); // $window.on('load', function () { // window.setTimeout(function () { // $body.removeClass('is-loading'); // }, 100); // }); // // Fix: Placeholder polyfill. // $('form').placeholder(); // // Prioritize "important" elements on medium. // skel.on('+medium -medium', function () { // $.prioritize( // '.important\\28 medium\\29', // skel.breakpoint('medium').active // ); // }); // // Scrolly. // $('.scrolly').scrolly({ // offset: function () { // return $header.height(); // } // }); // // Menu. // $('#menu') // .append('') // .appendTo($body) // .panel({ // delay: 500, // hideOnClick: true, // hideOnSwipe: true, // resetScroll: true, // resetForms: true, // side: 'right' // }); // }); //})(jQuery);