main.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467
  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_name = "MobiParc"
  28. var db_version = "3"
  29. var indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB || window.shimIndexedDB;
  30. var request;
  31. // Installe le service worker
  32. if ('serviceWorker' in navigator) {
  33. console.log("[ServiceWorker] Installe");
  34. navigator.serviceWorker.register('../sw.js');
  35. }
  36. var sectionId;
  37. var section;
  38. var load = function () {
  39. // Vide la section main
  40. $(".main").empty();
  41. // Page en cours
  42. sectionId = (window.location.hash.slice(1).length > 0 ? window.location.hash.slice(1) : "index");
  43. section = $("body").find('#' + sectionId);
  44. // compile la section avec handlebars
  45. if ($(section).attr("model")) {
  46. var model = $(section).attr("model");
  47. var template = Handlebars.compile(section.html());
  48. // Charge la base de données, et le stockage courant
  49. //var indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB || window.shimIndexedDB;
  50. request = indexedDB.open(db_name, db_version);
  51. var db;
  52. var txs;
  53. var store;
  54. // Cree les stockages necessaires si ceux ci sont manquants
  55. request.onupgradeneeded = function () {
  56. var db = request.result;
  57. db.createObjectStore(model, { keyPath: "guid" });
  58. console.log("[DB] Cree '" + model + "'");
  59. };
  60. request.onsuccess = function () {
  61. db = request.result;
  62. txs = db.transaction(model, "readonly");
  63. store = txs.objectStore(model);
  64. store.getAll().onsuccess = function (event) {
  65. var data = { data: event.target.result };
  66. $(".main").html(template(data));
  67. };
  68. };
  69. request.onerror = function () {
  70. console.log("Error while loading the db '" + model + "'");
  71. $(".main").html(template({}));
  72. return;
  73. };
  74. // Intercepte la soumision de formulaires
  75. $(".main").on("submit", ".data-form", function (event) {
  76. console.log("handle submit");
  77. var form = $(".main").find(".data-form")[0];
  78. // Stop the form from submitting since we’re handling that with AJAX.
  79. event.preventDefault();
  80. // Call our function to get the form data.
  81. var data = formToJSON(form.elements);
  82. //// DEMO ONLY: print the form data onscreen as a formatted JSON object.
  83. //var dataContainer = document.getElementsByClassName('results-display')[0];
  84. //// Use `JSON.stringify()` to make the output valid, human-readable JSON.
  85. //dataContainer.textContent = JSON.stringify(data, null, " ");
  86. data.guid = createGuid();
  87. //data.tstamp = Date.now();
  88. data.user = localStorage.hasOwnProperty("params") ? JSON.parse(localStorage.getItem("params")).user : "(unknown)";
  89. txs = db.transaction(model, "readwrite");
  90. store = txs.objectStore(model);
  91. store.put(data);
  92. store.getAll().onsuccess = function (event) {
  93. $(".main").empty();
  94. var data = { data: event.target.result };
  95. var template = Handlebars.compile(section.html());
  96. $(".main").html(template(data));
  97. };
  98. });
  99. // Gere le clic sur un bouton supprimer
  100. $("body").on("click", ".del", function (event) {
  101. var del = $(this);
  102. if (confirm("Supprimer la selection!") == true) {
  103. $(del).prop("disabled", true);
  104. $(".ui-selected").each(function () {
  105. var elt = $(this);
  106. var id = $(elt).data("id");
  107. //var datatype = $(elt).data("type");
  108. txs = db.transaction(model, "readwrite");
  109. store = txs.objectStore(model);
  110. store.delete(id).onsuccess = function (evt) {
  111. $(elt).remove();
  112. };
  113. });
  114. }
  115. });
  116. }
  117. else {
  118. //template = Handlebars.compile(section.html());
  119. //$(".main").html(template({}));
  120. $(".main").html(section.html());
  121. }
  122. }
  123. load();
  124. // Recharge dynamiquement le contenu HTML à chaque changement d'url
  125. $(window).on('hashchange', function () {
  126. console.log("Trigger: hashchange");
  127. load();
  128. });
  129. //######### MAIN ###############
  130. // ### Interactions
  131. // Affiche ou masque la sidebar
  132. $('.bt-menu').on('click', 'svg', function () {
  133. $(this).closest('nav').find('div:not(:first)').toggleClass('sidebar');
  134. });
  135. $(document).on('click', '.sidebar', function () {
  136. $(this).closest('nav').find('div:not(:first)').toggleClass('sidebar');
  137. });
  138. // Affiche ou masque le bouton de sync
  139. if (navigator.onLine) {
  140. $(".data-sync").removeAttr("disabled");
  141. }
  142. else {
  143. if (!$(".data-sync").is(":disabled"))
  144. {
  145. $(".data-sync").attr("disabled")
  146. }
  147. }
  148. /* retour haut de page*/
  149. window.onscroll = function (ev) {
  150. document.getElementById("cRetour").className = (window.pageYOffset > 100) ? "cVisible" : "cInvisible";
  151. };
  152. $('#cRetour').on('click', function () {
  153. $('html, body').animate({ scrollTop: 0 }, 200);
  154. });
  155. // Gere l'affichage des classes modales
  156. $(".modal-open, .modal-background, .modal-close").click(function () {
  157. $(".modal-content,.modal-background").toggleClass("active");
  158. if ($(this).hasClass("modal-close")) location.reload();
  159. });
  160. // Rend selectionables les lignes des tables (.selectable)
  161. $(".main").selectable({
  162. filter: ".selectable tr",
  163. stop: function () {
  164. $(".del").removeAttr("disabled");
  165. }
  166. });
  167. // ### Synchronisation des données
  168. $(".data-sync").on("click", function () {
  169. if (!request) {
  170. request = indexedDB.open(db_name, db_version);
  171. request.onerror = function () {
  172. console.log("Error while accessing the db");
  173. alert("Erreur: impossible d'accéder à la base de données locale.");
  174. return;
  175. };
  176. }
  177. var db = request.result;
  178. var txs = db.transaction("activites", "readonly");
  179. var stores = txs.objectStore("activites");
  180. console.log("post all");
  181. stores.openCursor().onsuccess = function (event) {
  182. var cursor = event.target.result;
  183. if (cursor) {
  184. cursor.value.model = "activites";
  185. var id = cursor.value.guid;
  186. var posting = $.post("/api/mobiparc", { data: JSON.stringify(cursor.value) });
  187. // Put the results in a div
  188. posting.done(function (data) {
  189. if (data == true) {
  190. var tx = db.transaction("activites", "readwrite");
  191. var store = tx.objectStore("activites");
  192. store.delete(id).onsuccess = function (evt) {
  193. $('.sync-result').append("Sync ok activite : " + id + "<br>");
  194. };
  195. }
  196. });
  197. cursor.continue();
  198. }
  199. else {
  200. console.log("end activite");
  201. }
  202. };
  203. })
  204. //###### TOOLBOX ######
  205. function createGuid() {
  206. return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c =>
  207. (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
  208. )
  209. }
  210. function getLocation() {
  211. try {
  212. if (navigator.geolocation) {
  213. navigator.geolocation.getCurrentPosition(showPosition);
  214. } else {
  215. console.log("Geolocation is not supported by this browser.");
  216. return 0;
  217. }
  218. }
  219. catch (e) {
  220. console.log("Geolocation: error");
  221. }
  222. }
  223. function showPosition(position) {
  224. $("input[name='coordinates']").val(position.coords.latitude + "," + position.coords.longitude);
  225. console.log(position.coords);
  226. }
  227. // ### Serialization
  228. /**
  229. * Checks that an element has a non-empty `name` and `value` property.
  230. * @param {Element} element the element to check
  231. * @return {Bool} true if the element is an input, false if not
  232. */
  233. var isValidElement = function isValidElement(element) {
  234. return element.name && element.value;
  235. };
  236. /**
  237. * Checks if an element’s value can be saved (e.g. not an unselected checkbox).
  238. * @param {Element} element the element to check
  239. * @return {Boolean} true if the value should be added, false if not
  240. */
  241. var isValidValue = function isValidValue(element) {
  242. return !['checkbox', 'radio'].includes(element.type) || element.checked;
  243. };
  244. /**
  245. * Checks if an input is a checkbox, because checkboxes allow multiple values.
  246. * @param {Element} element the element to check
  247. * @return {Boolean} true if the element is a checkbox, false if not
  248. */
  249. var isCheckbox = function isCheckbox(element) {
  250. return element.type === 'checkbox';
  251. };
  252. //var isHidden = function isHidden(element) {
  253. // return element.type === 'hidden';
  254. //};
  255. /**
  256. * Checks if an input is a `select` with the `multiple` attribute.
  257. * @param {Element} element the element to check
  258. * @return {Boolean} true if the element is a multiselect, false if not
  259. */
  260. var isMultiSelect = function isMultiSelect(element) {
  261. return element.options && element.multiple;
  262. };
  263. /**
  264. * Retrieves the selected options from a multi-select as an array.
  265. * @param {HTMLOptionsCollection} options the options for the select
  266. * @return {Array} an array of selected option values
  267. */
  268. var getSelectValues = function getSelectValues(options) {
  269. return [].reduce.call(options, function (values, option) {
  270. return option.selected ? values.concat(option.value) : values;
  271. }, []);
  272. };
  273. /**
  274. * A more verbose implementation of `formToJSON()` to explain how it works.
  275. *
  276. * NOTE: This function is unused, and is only here for the purpose of explaining how
  277. * reducing form elements works.
  278. *
  279. * @param {HTMLFormControlsCollection} elements the form elements
  280. * @return {Object} form data as an object literal
  281. */
  282. var formToJSON_deconstructed = function formToJSON_deconstructed(elements) {
  283. // This is the function that is called on each element of the array.
  284. var reducerFunction = function reducerFunction(data, element) {
  285. // Add the current field to the object.
  286. data[element.name] = element.value;
  287. // For the demo only: show each step in the reducer’s progress.
  288. console.log(JSON.stringify(data));
  289. return data;
  290. };
  291. // This is used as the initial value of `data` in `reducerFunction()`.
  292. var reducerInitialValue = {};
  293. // To help visualize what happens, log the inital value, which we know is `{}`.
  294. console.log('Initial `data` value:', JSON.stringify(reducerInitialValue));
  295. // Now we reduce by `call`-ing `Array.prototype.reduce()` on `elements`.
  296. var formData = [].reduce.call(elements, reducerFunction, reducerInitialValue);
  297. // The result is then returned for use elsewhere.
  298. return formData;
  299. };
  300. /**
  301. * Retrieves input data from a form and returns it as a JSON object.
  302. * @param {HTMLFormControlsCollection} elements the form elements
  303. * @return {Object} form data as an object literal
  304. */
  305. var formToJSON = function formToJSON(elements) {
  306. return [].reduce.call(elements, function (data, element) {
  307. // Make sure the element has the required properties and should be added.
  308. if (isValidElement(element) && isValidValue(element)) {
  309. /*
  310. * Some fields allow for more than one value, so we need to check if this
  311. * is one of those fields and, if so, store the values as an array.
  312. */
  313. if (isCheckbox(element)) {
  314. data[element.name] = (data[element.name] || []).concat(element.value);
  315. } else if (isMultiSelect(element)) {
  316. data[element.name] = getSelectValues(element);
  317. } else {
  318. data[element.name] = element.value;
  319. }
  320. }
  321. return data;
  322. }, {});
  323. };
  324. /*
  325. Intensify by TEMPLATED
  326. templated.co @templatedco
  327. Released for free under the Creative Commons Attribution 3.0 license (templated.co/license)
  328. */
  329. (function ($) {
  330. skel.breakpoints({
  331. xlarge: '(max-width: 1680px)',
  332. large: '(max-width: 1280px)',
  333. medium: '(max-width: 980px)',
  334. small: '(max-width: 736px)',
  335. xsmall: '(max-width: 480px)'
  336. });
  337. $(function () {
  338. var $window = $(window),
  339. $body = $('body'),
  340. $header = $('#header');
  341. // Disable animations/transitions until the page has loaded.
  342. $body.addClass('is-loading');
  343. $window.on('load', function () {
  344. window.setTimeout(function () {
  345. $body.removeClass('is-loading');
  346. }, 100);
  347. });
  348. // Fix: Placeholder polyfill.
  349. $('form').placeholder();
  350. // Prioritize "important" elements on medium.
  351. skel.on('+medium -medium', function () {
  352. $.prioritize(
  353. '.important\\28 medium\\29',
  354. skel.breakpoint('medium').active
  355. );
  356. });
  357. // Scrolly.
  358. $('.scrolly').scrolly({
  359. offset: function () {
  360. return $header.height();
  361. }
  362. });
  363. // Menu.
  364. $('#menu')
  365. .append('<a href="#menu" class="close"></a>')
  366. .appendTo($body)
  367. .panel({
  368. delay: 500,
  369. hideOnClick: true,
  370. hideOnSwipe: true,
  371. resetScroll: true,
  372. resetForms: true,
  373. side: 'right'
  374. });
  375. });
  376. })(jQuery);