mobiparc.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393
  1. // requires jquery 1.7+
  2. // JS s'execute: Retire l'avertissement 'Javascript est requis' (de fait, on sait que JS est actif...)
  3. document.body.classList.remove("nojs");
  4. //### Helpers handlebars personnalisés
  5. Handlebars.registerHelper('lower', function (options) {
  6. return options.fn(this).toLowerCase();
  7. });
  8. Handlebars.registerHelper('repuri', function (find, replace, options) {
  9. return encodeURI(options.fn(this).replace(find, replace).toString());
  10. });
  11. Handlebars.registerHelper('todate', function (options) {
  12. var d = options.fn(this);
  13. var dt = new Date(Number.parseInt(d) * 1);
  14. return dt.toLocaleString();
  15. });
  16. Handlebars.registerHelper('timestamp', function (options) {
  17. return Number.parseInt(options.fn(this));
  18. });
  19. Handlebars.registerHelper('if_eq', function (a, opts) {
  20. var b = localStorage.hasOwnProperty("contact") ? localStorage.getItem("contact") : "";
  21. if (a === b) // Or === depending on your needs
  22. return opts.fn(this);
  23. else
  24. return opts.inverse(this);
  25. });
  26. //### Initialisation
  27. var db_version = "3"
  28. // Installe le service worker
  29. if ('serviceWorker' in navigator) {
  30. console.log("[ServiceWorker] Installe");
  31. navigator.serviceWorker.register('../sw.js');
  32. }
  33. var sectionId;
  34. var section;
  35. var load = function () {
  36. // Vide la section main
  37. $("#main").empty();
  38. // Page en cours
  39. sectionId = (window.location.hash.slice(1).length > 0 ? window.location.hash.slice(1) : "index");
  40. section = $("body").find('#' + sectionId);
  41. // compile la section avec handlebars
  42. if ($(section).attr("model")) {
  43. var model = $(section).attr("model");
  44. var template = Handlebars.compile(section.html());
  45. // Charge la base de données, et le stockage courant
  46. var indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB || window.shimIndexedDB;
  47. var request = indexedDB.open("MobiParc", db_version);
  48. var db;
  49. var txs;
  50. var store;
  51. // Cree les stockages necessaires si ceux ci sont manquants
  52. request.onupgradeneeded = function () {
  53. var db = request.result;
  54. db.createObjectStore(model, { keyPath: "tstamp" });
  55. console.log("[DB] Cree '" + model + "'");
  56. };
  57. request.onsuccess = function () {
  58. db = request.result;
  59. txs = db.transaction(model, "readonly");
  60. store = txs.objectStore(model);
  61. store.getAll().onsuccess = function (event) {
  62. var data = { data: event.target.result };
  63. $("#main").html(template(data));
  64. };
  65. };
  66. request.onerror = function () {
  67. console.log("Error while loading the db '" + model + "'");
  68. $("#main").html(template({}));
  69. return;
  70. };
  71. // Intercepte la soumision de formulaires
  72. $("#main").on("submit", ".data-form", function (event) {
  73. console.log("handle submit");
  74. var form = $("#main").find(".data-form")[0];
  75. // Stop the form from submitting since we’re handling that with AJAX.
  76. event.preventDefault();
  77. // Call our function to get the form data.
  78. var data = formToJSON(form.elements);
  79. // Demo only: print the form data onscreen as a formatted JSON object.
  80. var dataContainer = document.getElementsByClassName('results-display')[0];
  81. // Use `JSON.stringify()` to make the output valid, human-readable JSON.
  82. dataContainer.textContent = JSON.stringify(data, null, " ");
  83. if ($(form).hasClass("activite")) {
  84. data.tstamp = Date.now();
  85. data.user = localStorage.hasOwnProperty("params") ? JSON.parse(localStorage.getItem("params")).user : "(unknown)";
  86. txs = db.transaction(model, "readwrite");
  87. store = txs.objectStore(model);
  88. store.put(data);
  89. store.getAll().onsuccess = function (event) {
  90. $("#main").empty();
  91. var data = { data: event.target.result };
  92. var template = Handlebars.compile(section.html());
  93. $("#main").html(template(data));
  94. };
  95. }
  96. });
  97. // Gere le clic sur un bouton supprimer
  98. $("body").on("click", ".del", function (event) {
  99. var del = $(this);
  100. if (confirm("Supprimer la selection!") == true) {
  101. $(del).prop("disabled", true);
  102. $(".ui-selected").each(function () {
  103. var elt = $(this);
  104. var id = $(elt).data("id");
  105. //var datatype = $(elt).data("type");
  106. txs = db.transaction(model, "readwrite");
  107. store = txs.objectStore(model);
  108. store.delete(id).onsuccess = function (evt) {
  109. $(elt).remove();
  110. };
  111. });
  112. }
  113. });
  114. }
  115. else {
  116. $("#main").html($(section).html());
  117. }
  118. }
  119. load();
  120. // Recharge dynamiquement le contenu HTML à chaque changement d'url
  121. $(window).on('hashchange', function () {
  122. console.log("Trigger: hashchange");
  123. load();
  124. });
  125. //######### MAIN ###############
  126. // ### Interactions
  127. // Affiche ou masque la sidebar
  128. $('.bt-menu').on('click', 'svg', function () {
  129. $(this).closest('nav').find('div:not(:first)').toggleClass('sidebar');
  130. });
  131. $(document).on('click', '.sidebar', function () {
  132. $(this).closest('nav').find('div:not(:first)').toggleClass('sidebar');
  133. });
  134. // Affiche ou masque le bouton de sync
  135. if (navigator.onLine) {
  136. $(".data-sync").removeAttr("disabled");
  137. }
  138. else {
  139. if (!$(".data-sync").is(":disabled"))
  140. {
  141. $(".data-sync").attr("disabled")
  142. }
  143. }
  144. /* retour haut de page*/
  145. window.onscroll = function (ev) {
  146. document.getElementById("cRetour").className = (window.pageYOffset > 100) ? "cVisible" : "cInvisible";
  147. };
  148. $('#cRetour').on('click', function () {
  149. $('html, body').animate({ scrollTop: 0 }, 200);
  150. });
  151. // Gere l'affichage des classes modales
  152. $(".modal-open, .modal-background, .modal-close").click(function () {
  153. $(".modal-content,.modal-background").toggleClass("active");
  154. if ($(this).hasClass("modal-close")) location.reload();
  155. });
  156. // Rend selectionables les lignes des tables (.selectable)
  157. $("#main").selectable({
  158. filter: ".selectable tr",
  159. stop: function () {
  160. $(".del").removeAttr("disabled");
  161. }
  162. });
  163. // ### Synchronisation des données
  164. $(".data-sync").on("click", function () {
  165. var db = open.result;
  166. var txs = db.transaction("activite", "readonly");
  167. var stores = txs.objectStore("activite");
  168. console.log("post all : ");
  169. stores.openCursor().onsuccess = function (event) {
  170. //var data = { data: event.target.result };
  171. var cursor = event.target.result;
  172. if (cursor) {
  173. //cursor.model = "anomaly";
  174. cursor.value.model = "activite";
  175. var id = cursor.value.tstamp;
  176. var posting = $.post("/api/mobiparc", { data: JSON.stringify(cursor.value) });
  177. // Put the results in a div
  178. posting.done(function (data) {
  179. if (data == 'ole') {
  180. var tx = db.transaction("activite", "readwrite");
  181. var store = tx.objectStore("activite");
  182. store.delete(id).onsuccess = function (evt) {
  183. $('.sync-result').append("Sync ok activite : " + id + "<br>");
  184. };
  185. }
  186. });
  187. cursor.continue();
  188. }
  189. else {
  190. console.log("end activite");
  191. }
  192. };
  193. })
  194. //###### TOOLBOX ######
  195. function createGuid() {
  196. return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c =>
  197. (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
  198. )
  199. }
  200. function getLocation() {
  201. try {
  202. if (navigator.geolocation) {
  203. navigator.geolocation.getCurrentPosition(showPosition);
  204. } else {
  205. console.log("Geolocation is not supported by this browser.");
  206. return 0;
  207. }
  208. }
  209. catch (e) {
  210. console.log("Geolocation: error");
  211. }
  212. }
  213. function showPosition(position) {
  214. $("input[name='coordinates']").val(position.coords.latitude + "," + position.coords.longitude);
  215. console.log(position.coords);
  216. }
  217. // ### Serialization
  218. /**
  219. * Checks that an element has a non-empty `name` and `value` property.
  220. * @param {Element} element the element to check
  221. * @return {Bool} true if the element is an input, false if not
  222. */
  223. var isValidElement = function isValidElement(element) {
  224. return element.name && element.value;
  225. };
  226. /**
  227. * Checks if an element’s value can be saved (e.g. not an unselected checkbox).
  228. * @param {Element} element the element to check
  229. * @return {Boolean} true if the value should be added, false if not
  230. */
  231. var isValidValue = function isValidValue(element) {
  232. return !['checkbox', 'radio'].includes(element.type) || element.checked;
  233. };
  234. /**
  235. * Checks if an input is a checkbox, because checkboxes allow multiple values.
  236. * @param {Element} element the element to check
  237. * @return {Boolean} true if the element is a checkbox, false if not
  238. */
  239. var isCheckbox = function isCheckbox(element) {
  240. return element.type === 'checkbox';
  241. };
  242. //var isHidden = function isHidden(element) {
  243. // return element.type === 'hidden';
  244. //};
  245. /**
  246. * Checks if an input is a `select` with the `multiple` attribute.
  247. * @param {Element} element the element to check
  248. * @return {Boolean} true if the element is a multiselect, false if not
  249. */
  250. var isMultiSelect = function isMultiSelect(element) {
  251. return element.options && element.multiple;
  252. };
  253. /**
  254. * Retrieves the selected options from a multi-select as an array.
  255. * @param {HTMLOptionsCollection} options the options for the select
  256. * @return {Array} an array of selected option values
  257. */
  258. var getSelectValues = function getSelectValues(options) {
  259. return [].reduce.call(options, function (values, option) {
  260. return option.selected ? values.concat(option.value) : values;
  261. }, []);
  262. };
  263. /**
  264. * A more verbose implementation of `formToJSON()` to explain how it works.
  265. *
  266. * NOTE: This function is unused, and is only here for the purpose of explaining how
  267. * reducing form elements works.
  268. *
  269. * @param {HTMLFormControlsCollection} elements the form elements
  270. * @return {Object} form data as an object literal
  271. */
  272. var formToJSON_deconstructed = function formToJSON_deconstructed(elements) {
  273. // This is the function that is called on each element of the array.
  274. var reducerFunction = function reducerFunction(data, element) {
  275. // Add the current field to the object.
  276. data[element.name] = element.value;
  277. // For the demo only: show each step in the reducer’s progress.
  278. console.log(JSON.stringify(data));
  279. return data;
  280. };
  281. // This is used as the initial value of `data` in `reducerFunction()`.
  282. var reducerInitialValue = {};
  283. // To help visualize what happens, log the inital value, which we know is `{}`.
  284. console.log('Initial `data` value:', JSON.stringify(reducerInitialValue));
  285. // Now we reduce by `call`-ing `Array.prototype.reduce()` on `elements`.
  286. var formData = [].reduce.call(elements, reducerFunction, reducerInitialValue);
  287. // The result is then returned for use elsewhere.
  288. return formData;
  289. };
  290. /**
  291. * Retrieves input data from a form and returns it as a JSON object.
  292. * @param {HTMLFormControlsCollection} elements the form elements
  293. * @return {Object} form data as an object literal
  294. */
  295. var formToJSON = function formToJSON(elements) {
  296. return [].reduce.call(elements, function (data, element) {
  297. // Make sure the element has the required properties and should be added.
  298. if (isValidElement(element) && isValidValue(element)) {
  299. /*
  300. * Some fields allow for more than one value, so we need to check if this
  301. * is one of those fields and, if so, store the values as an array.
  302. */
  303. if (isCheckbox(element)) {
  304. data[element.name] = (data[element.name] || []).concat(element.value);
  305. } else if (isMultiSelect(element)) {
  306. data[element.name] = getSelectValues(element);
  307. } else {
  308. data[element.name] = element.value;
  309. }
  310. }
  311. return data;
  312. }, {});
  313. };