1 /* -*- coding: utf-8 -*- */
2 /** \file OPiQuotations.js
6 * JavaScript functions to
7 * - highlight founded words
8 * - init sharing buttons
9 * - open/close about panel
10 * - open/close AJAX lists
11 * - open/close AJAX sharing panel
12 * - open/close control panel.
14 * Piece of OPiQuotations.
15 * https://bitbucket.org/OPiMedia/opiquotations
17 * GPLv3 --- Copyright (C) 2014, 2015, 2016 Olivier Pirson
18 * http://www.opimedia.be/
23 * true if highlight is active,
26 var highlightActive = false;
31 * The stylesheet to modify.
33 var highlightSheet = null;
39 * Close the about panel.
41 function aboutClose() {
44 cssClassRemove(document.getElementById("about"), "opened");
50 * Open the about panel.
52 function aboutOpen() {
55 cssClassAdd(document.getElementById("about"), "opened");
61 * AJAX load the list name, if necessary.
65 function buildList(name) {
68 console.assert(typeof name === "string", name);
70 if (document.getElementById("list-" + name + "-list") !== null) { // already loaded
74 var xhr = new XMLHttpRequest();
76 xhr.open("GET", "OPiQuotations-list.php?list=" + name + "s", true);
77 xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
79 xhr.onreadystatechange = function() { // callback
80 if ((xhr.readyState !== 4) || (xhr.status !== 200)) {
84 var list = JSON.parse(xhr.responseText);
85 var containerItem = document.getElementById("list-" + name + "-container");
87 if (!list || (list.length === 0)) {
88 containerItem.innerHTML = ""; // remove loading message
93 // Add number of items
94 document.getElementById("list-" + name + "-nb").innerHTML = list.length;
96 // Calculate min and max of occurrences
98 var min = Number.MAX_VALUE;
103 nbOccurrence = list[i][1];
104 min = Math.min(min, nbOccurrence);
105 max = Math.max(max, nbOccurrence);
109 var ulItem = document.createElement("ul");
111 ulItem.setAttribute("id", "list-" + name + "-list");
118 aItem = document.createElement("a");
121 nbOccurrence = list[i][1];
123 percent = (nbOccurrence - min)*120/(max - min) + 80; // between 80% and 200%
125 cssClassAdd(aItem, (nbOccurrence === min
127 : (nbOccurrence === max
131 aItem.setAttribute("href", encodeURI("?" + name + "=" + value));
132 aItem.setAttribute("title", nbOccurrence + " citation" + (nbOccurrence > 1
135 aItem.style.fontSize = Math.round(percent) + "%";
137 aItem.appendChild(document.createTextNode(value));
139 ulItem.appendChild(document.createElement("li")).appendChild(aItem);
142 containerItem.innerHTML = ""; // remove loading message
143 containerItem.appendChild(ulItem);
152 * Close the control panel (in responsive mode),
153 * and eventually the about panel.
155 function controlPanelClose() {
158 cssClassRemove(document.getElementById("control-panel"), "opened");
165 * Open the control panel (in responsive mode).
167 function controlPanelOpen() {
170 cssClassAdd(document.getElementById("control-panel"), "opened");
176 * Add a CSS class to item.
179 * @param String className
181 function cssClassAdd(item, className) {
184 console.assert(item instanceof HTMLElement, item);
185 console.assert(typeof className === "string", className);
187 if (className !== "") {
189 item.classList.add(className);
191 catch (e) { // some old browsers and IE < 10
192 item.className += " " + className;
200 * Remove a CSS class to item.
203 * @param String className
205 function cssClassRemove(item, className) {
208 console.assert(item instanceof HTMLElement, item);
209 console.assert(typeof className === "string", className);
211 if (className !== "") {
213 item.classList.remove(className);
215 catch (e) { // some old browsers and IE < 10
216 var a = item.className.split(" ");
217 var i = a.indexOf(className);
222 item.className = a.join(" ");
230 * Switch on/off all highlighted words
231 * and close the control panel (in responsive mode).
233 function highlightOnOff() {
236 if (highlightSheet !== null) {
237 if (highlightActive) {
238 highlightSheet.deleteRule(0);
239 highlightSheet.deleteRule(0);
242 highlightSheet.insertRule("main > section.quotation mark { background-color: yellow !important; }", 0);
243 highlightSheet.insertRule("main > section.maxim mark { background-color: #ffbda0 !important; }", 1);
245 highlightActive = !highlightActive;
254 * Close all lists in panel,
257 * Load the list name, if necessary.
261 function listOpen(name) {
264 console.assert(typeof name === "string", name);
269 document.getElementById("list-" + name).style.display = "block";
277 * Close all lists in panel.
279 function listsHide() {
282 var labels = ["author", "nation", "subject", "work"];
287 document.getElementById("list-" + labels[i]).style.display = "none";
294 * Close this sharing panel.
296 * @param: DOM liCloseItem
298 function sharingClose(liCloseItem) {
301 console.assert(liCloseItem instanceof HTMLElement, liCloseItem);
303 var ul = liCloseItem.parentNode;
305 ul.parentNode.removeChild(ul);
311 * Open the sharing panel for the quotation id
312 * in a <ul> sibling of item.
315 * @param integer id > 0
317 function sharingOpen(item, id) {
320 console.assert(item instanceof HTMLElement, item);
321 console.assert(Number.isInteger(id), id);
322 console.assert(id > 0, id);
324 if (!item || !id || (id <= 0)) {
328 var parent = item.parentNode;
330 // If panel already open, then remove sibling items of item
331 if (parent.children.length > 1) {
332 while (parent.children.length > 1) {
333 parent.removeChild(parent.children[1]);
339 // Create <ul> and fill it in AJAX
340 var ul = document.createElement("ul");
342 ul.setAttribute("aria-haspopup", "true");
344 ul.innerHTML = "<li>Chargement…</li>";
345 parent.appendChild(ul);
347 var xhr = new XMLHttpRequest();
349 xhr.open("GET", "OPiQuotations-sharing.php?id=" + id, true);
350 xhr.setRequestHeader("Content-Type", "text/html;charset=UTF-8");
352 xhr.onreadystatechange = function() { // callback
353 if ((xhr.readyState !== 4) || (xhr.status !== 200 || !xhr.responseText)) {
356 ul.innerHTML = xhr.responseText;
371 // Search the good stylesheet
373 for (i = 0; i < document.styleSheets.length; ++i) {
374 highlightSheet = document.styleSheets[i];
376 if (highlightSheet.title === "highlight") {
382 // Set listener to on/off highlight
383 var item = document.getElementById("highlight-on-off");
386 item.addEventListener("click", highlightOnOff, false);
389 // Set listeners to open/close about panel
390 document.getElementById("about-open").addEventListener("click", aboutOpen, false);
391 document.getElementById("about-close").addEventListener("click", aboutClose, false);
394 // Set listeners to open/close control panel
395 document.getElementById("control-panel-right-border").addEventListener("click", controlPanelOpen, false);
396 document.getElementById("control-panel-close").addEventListener("click", controlPanelClose, false);
399 // Set listeners to open/close lists
400 var buttons = document.getElementById("lists").getElementsByClassName("close");
402 for (i = 0; i < buttons.length; ++i) {
403 buttons[i].addEventListener("click", listsHide, false);
406 buttons = document.getElementById("menu").getElementsByClassName("list-open");
407 for (i = 0; i < buttons.length; ++i) {
409 buttons[i].addEventListener("click",
413 }(buttons[i].parentNode.parentNode.className));