Commit 5dd3be65 authored by Oncela's avatar Oncela

Validation initiale

 Modifications qui seront validées :
	nouveau fichier : README.md
	nouveau fichier : admin/updateServer.php
	nouveau fichier : click.js
	nouveau fichier : construct.js
	nouveau fichier : index.html
	nouveau fichier : init.js
	nouveau fichier : irc.js
	nouveau fichier : option.js
	nouveau fichier : pad.js
	nouveau fichier : server/deleted.json
	nouveau fichier : server/menu.json
	nouveau fichier : style.css
	nouveau fichier : update.js
	nouveau fichier : updateClient.php
parents
<?php
/* ----------------------
Mise à jour du serveur
---------------------- */
// L'emplacement du fichier contenant le menu
$file = "../server/menu.json";
// L'emplacement du fichier contenant les éléments supprimés
$deletedFile = "../server/deleted.json";
// Lorsque reçoit une demande de mise à jour du serveur
if (isset($_POST['updateServer']))
{
// Recupère l'objet principal contenu dans le fichier
$content = json_decode(file_get_contents($file));
// Recupère le type de la modification, spécifié par la demande
$type = $_POST['updateServer'];
// Recupère le contenu de la modification, spécifié par la demande
$info = $_POST['info'];
// Recupère la position de l'élément du menu à partir duquel faire la modification, spécifiée par la demande
$path = str_split($_POST['path']);
// Renomme
if ($type == "newName")
$content = newName($content, $info, $path);
// Ajoute
else if ($type == "newPage" || $type == "newFolder")
$content = addElement($content, $info, $path, $type);
// Déplace
else if ($type == "move")
$content = moveElement($content, $info, $path);
// Supprime
else if ($type == "delete")
$content = deleteElement($content, $path);
// Met à jour l'objet principal du fichier
file_put_contents ($file, json_encode($content));
// Envoie au client le contenu du tableau de l'objet principal
echo json_encode($content->content);
}
/* ----------------------
Créer un élément
---------------------- */
function createElement($title, $type)
{
// Crée un nouvel élément
$element = new stdClass;
// Donne au nouvel élément le titre celui indiquée par la demande
$element->title = $title;
// Donne au nouvel élément un ID aléatoire
$element->id = rand(10000000, 99999999);
// Si la demande concerne l'ajout d'une page
if ($type == "newPage")
{
// Donne à l'élément le type "page"
$element->type = "page";
}
// Si la demande concerne l'ajout d'un dossier
else if ($type == "newFolder")
{
// Donne à l'élément le type "folder"
$element->type = "folder";
// Donne à l'élément un tableau qui contiendra ses sous-éléments
$element->content = [];
}
return $element;
}
/* ----------------------
Récupérer un élément
---------------------- */
function getElement($content, $path)
{
$element = $content;
for ($i = 0; $i < count($path); $i++)
{
$element = $element->content[$path[$i]];
}
return $element;
}
/* ----------------------
Récupérer le parent d'un élément
---------------------- */
function getParent($content, $path)
{
$element = $content;
for ($i = 0; $i < count($path) -1; $i++)
{
$element = $element->content[$path[$i]];
}
return $element;
}
/* ----------------------
Renomer
---------------------- */
function newName($content, $info, $path)
{
// Recupère l'élément
$element = getElement($content, $path);
// Donne à l'élément le titre indiqué
$element->title = $info;
// Renvoie l'objet principal modifié
return $content;
}
/* ----------------------
Insérer
---------------------- */
function insertElement($content, $path, $element)
{
// Recupère l'élément cliqué (en fonction duquel le nouvel élément doit être ajouté)
$syb = getElement($content, $path);
// Si l'élément cliqué est un dossier
if ($syb->type == "folder")
{
// Ajoute le nouvel élément au début du dossier
array_unshift($syb->content, $element);
}
// Si l'élément cliqué est une page
else if ($syb->type == "page")
{
// Recupère le dossier parent de la page cliquée
$parent = getParent($content, $path);
// Ajoute le nouvel élément dans le dossier parent, après la page cliquée
array_splice( $parent->content, $path[ count($path) -1 ] +1 , 0, array ( $element ) );
}
return $content;
}
/* ----------------------
Ajouter un nouvel élément
---------------------- */
function addElement($content, $info, $path, $type)
{
// Crée un nouvel élément
$newElement = createElement($info, $type);
return insertElement($content, $path, $newElement);
}
/* ----------------------
Déplacer
---------------------- */
function moveElement($content, $pathTo, $path)
{
$pathTo=str_split($pathTo);
// Vérifie que l'élément à déplacer n'est pas un parent du dossier où on cherche à le déplacer
$continue = false;
if ( count($pathTo) >= count($path) )
{
for ($i = 0; $i < count($path) AND $continue == false; $i++)
{
if ( $pathTo[$i] != $path[$i] )
$continue = true;
}
}
else
{
$continue = true;
}
if ($continue)
{
// Récupère l'élément à déplacer
$element = getElement($content, $path);
// Récupère le parent de l'élément à déplacer
$parent = getParent($content, $path);
// Fait une cope de l'élément à déplacer
$elementCopy = clone $element;
// Indique que l'original de l'élément à déplacé doit être supprimé
$element->type = "removed";
// Insère la copie de l'élément à déplacer à l'endroit indiqué
$content = insertElement($content, $pathTo, $elementCopy);
// Supprime l'original de l'élément à déplacer
for ($i = 0; $i < count($parent->content); $i++)
{
if ($parent->content[$i]->type == "removed")
array_splice( $parent->content, $i , 1 );
}
}
return $content;
}
/* ----------------------
Supprimer
---------------------- */
function deleteElement($content, $path)
{
// Récupère l'élément à supprimer
$element = getElement($content, $path);
// Récupère son parent
$parent = getParent($content, $path);
// Met l'élément dans le fichier des éléments supprimés
file_put_contents ("server/deleted.json", json_encode( $element ), FILE_APPEND );
// Supprime l'élément de son parent
array_splice( $parent->content, $path[ count($path) -1 ] , 1 );
// Renvoie l'objet principal modifié
return $content;
}
?>
function click (e)
{
// Si le clic est fait alors que l'option de déplacement est en cours
if (option.move.active)
{
// Clic gauche
if (e.button == 0)
{
// Active le déplacement à partir de l'élément cliqué
option.move.from(this);
}
// Autre
else
{
e.preventDefault();
option.move.stop();
}
}
// Clic gauche
else if (e.button == 0)
{
// Si l'élément cliqué est le titre d'une page
if (this.classList.contains("page_title"))
{
// Ouvre la page dans l'iframe du pad
pad.open(this);
}
// Si l'élément cliqué est le titre d'un dossier
else if (this.classList.contains("folder_title"))
{
// Change la classe CSS du dossier
if (!this.classList.contains("open"))
{
this.classList.add("open");
}
else
{
this.classList.remove("open");
}
}
}
// Clic droit
else if (e.button == 2)
{
// Empêche l'option du navigateur de s'ouvrir (le clic droit par défaut)
e.preventDefault();
// Ouvre l'option, en lui passant l'élément cliqué et la position de la sourie
option.open(this, e.clientX, e.clientY);
}
}
// Construit chaque élément HTML du menu, à partir de son parent ("element") et de sa place sous ce parent ("index")
function construct ( element , index )
{
// Crée le <li> qui contiendra le titre de l'élément, et lui donne comme classe CSS le type de l'élément ("page" ou "folder")
var item = document.createElement("li");
item.innerHTML = element.title;
item.classList.add(element.type + "_title");
// Retient la position de l'élément dans la hiérarchie du menu, à partir de la position de l'élément parent ("this")
item.path = this.path + index;
// Associe le clic (gauche ou droite) à la fonction appropriée (définie dans < clickMenu.js >)
item.onclick = item.oncontextmenu = click;
// Intègre le <li> dans le <div> de son parent ("this")
this.appendChild(item);
// Donne à l'élément son ID
item.id = element.id;
// Si l'élément est une page
if (element.type == "page")
{
// Si aucune page par défaut n'est encore définit
if ( pad.def == null )
{
// Fait de la première page rencontrée celle ouverte par défaut
pad.def = item;
}
// Si l'ID de la page est celui indiqué dans l'URL
if ( element.id == parseInt ( window.location.hash.slice (1) ) )
{
// Fait de la page celle ouverte au démarage
pad.current = item;
}
}
// Si l'élément est un dossier
else if (element.type == "folder")
{
// Crée le <ul> qui contiendra les éléments du dossier
item.folder = document.createElement("ul");
// Donne à <ul> la classe CSS appropriée
item.folder.classList.add("folder_content");
// Conserve dans <ul> la même position que l'élément principal (pour le transmettre aux enfants)
item.folder.path = item.path;
// Construit les éléments du dossier, l'un après l'autre, en passant l'élément <ul> en paramètre
element.content.forEach(construct, item.folder);
// Intègre l'élement <ul> du dossier à l'élément
this.appendChild(item.folder);
}
}
<!DOCTYPE html><html>
<head>
<title>PadWiki</title>
<meta charset="UTF-8">
<link rel="stylesheet" href="style.css">
</head>
<body>
</body>
<!-- Initialise la page -->
<script src="init.js"></script>
<!-- Construit le menu -->
<script src="construct.js"></script>
<!-- Répond aux clics sur le menu -->
<script src="click.js"></script>
<!-- Actions modifiant le menu -->
<script src="option.js"></script>
<!-- Met à jour le serveur -->
<script src="update.js"></script>
<!-- Affiche les pages dans le pad -->
<script src="pad.js"></script>
<!-- Applet IRC -->
<script src="irc.js"></script>
</html>
// Lorsque la page et ses scripts sont chargés
onload = function ()
{
// Ajoute un ément HTML pour contenir le menu
menu = document.createElement("menu");
menu.id = "menu";
menu.path= "";
document.body.appendChild(menu);
// Établie une connexion avec le serveur
server = new XMLHttpRequest();
server.open("POST", 'updateClient.php', true);
server.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
// Demande au serveur le contenu du menu
server.send("updateClient=1");
// Lorsque la réponse à la requête est reçue
server.onreadystatechange = function()
{
if (this.readyState == XMLHttpRequest.DONE && this.status == 200)
{
// Récupère le menu et le parse dans un tableau
var response = JSON.parse(server.responseText);
// Construit le menu à partir de chacun de ses éléments de premier niveau
response.forEach(construct, menu);
// Initialise le pad
pad.start();
// Initialise l'applet IRC
irc.start();
}
}
}
var irc = document.createElement("iframe");
irc.id = "irc";
irc.src = "https://demo.thelounge.chat/";
irc.start = function()
{
document.body.appendChild(irc);
}
// Élément HTML du menu d'options
var option = document.createElement("div");
option.id = "option";
option.classList.add("hidden");
document.body.appendChild(option);
// Ouverture du menu
option.open = function ( element, x, y )
{
this.target = element;
this.classList.remove("hidden");
this.style.left = (x - 20) + "px";
this.style.top = (y - 10) + "px";
// Affiche/ cache l'option "ouvrir dans un nouvel onglet" si l'élément est une page/ un dossier
if (element.classList.contains("page_title") && option.newTab.classList.contains("hidden"))
option.newTab.classList.remove("hidden");
else if (element.classList.contains("folder_title") && !option.newTab.classList.contains("hidden"))
option.newTab.classList.add("hidden");
}
// Fermeture du menu (lorsqu'appelée ou lorsque la sourie sors de l'élément HTML)
option.close = option.onmouseleave = function ()
{
this.classList.add("hidden");
}
// Ouvrir dans un nouvel onglet (seulement pour les pages)
option.newTab = document.createElement("div");
option.newTab.link = document.createElement("a");
option.newTab.link.target = "_blank";
option.newTab.link.innerHTML = "Ouvrir dans un nouvel onglet";
option.newTab.onclick = function()
{
this.link.href = pad.adress + option.target.id;
};
option.newTab.appendChild(option.newTab.link);
option.appendChild(option.newTab);
// Renommer un élément
option.rename = document.createElement("div");
option.rename.innerHTML = "Renommer";
option.rename.onclick = function()
{
var name = prompt("Renommer", option.target.innerHTML);
if (name != null)
{
update("newName", name, option.target.path);
}
}
option.appendChild(option.rename);
// Ajouter une page
option.newPage = document.createElement("div");
option.newPage.innerHTML = "Ajouter une page";
option.newPage.onclick = function()
{
var name = prompt("Titre de la nouvelle page");
if (name != null)
{
update("newPage", name, option.target.path);
}
}
option.appendChild(option.newPage);
// Ajouter un dossier
option.newFolder = document.createElement("div");
option.newFolder.innerHTML = "Ajouter un dossier";
option.newFolder.onclick = function()
{
var name = prompt("Titre du nouveau dossier");
if (name != null)
{
update("newFolder", name, option.target.path);
}
}
option.appendChild(option.newFolder);
// Déplacer
option.move = document.createElement("div");
option.move.innerHTML = "Déplacer";
option.move.active = false;
option.move.onclick = function()
{
var elements = menu.getElementsByTagName("li");
for (var i = 0; i < elements.length; i++)
{
elements[i].style.cursor = "s-resize";
}
option.move.active = true;
option.close();
}
option.move.from = function (from)
{
update("move", from.path, option.target.path);
this.stop();
}
option.move.stop = function()
{
var elements = menu.getElementsByTagName("li");
for (var i = 0; i < elements.length; i++)
{
elements[i].style.cursor = "pointer";
}
option.move.active = false;
}
option.appendChild(option.move);
// Supprime
option.deleted = document.createElement("div");
option.deleted.innerHTML = "Supprimer";
option.deleted.onclick = function()
{
if (confirm("Voulez-vous vraiment supprimer " + (option.target.classList.contains("page_title") ? "la page" : "le dossier") + " <" + option.target.innerHTML + "> ?"))
update("delete", "", option.target.path);
option.close();
}
option.appendChild(option.deleted);
// Iframe du pad
var pad = document.createElement("iframe");
pad.id = "pad";
pad.adress = "https://pad.lqdn.fr/p/test_padwikirc";
pad.current = null;
pad.def = null;
// Ouvre une nouvelle page dans le pad
pad.open = function (element)
{
this.src = this.adress + element.id;
if (this.current != null)
{
this.current.classList.remove("selected");
}
this.current = element;
this.current.classList.add("selected");
window.location.hash = element.id;
}
// Démarre le pad
pad.start = function()
{
// Intègre l'iframe
document.body.appendChild(pad);
// Si aucune page n'est visée dans le hash de l'URL
if (this.current == null)
{
// Vise la page par défaut
this.current = this.def;
}
// Ouvre la page
pad.open(this.current);
// Déplie les dossiers correspondants dans le menu
var child = this.current;
for (var i = 0; i < this.current.path.length-1; i++)
{
var parent = child.parentNode.previousSibling;
parent.classList.add("open");
child = parent;
}
}
null{"title":"kikou","id":47432773,"type":"folder","content":[{"title":"iori","id":29464909,"type":"page"},{"title":"chouchou","id":47601201,"type":"page"}]}{"title":"kikouu ;)","id":15939827,"type":"folder","content":[]}00{"title":"test","type":"page","id":11310313}0{"title":"test9","id":80992250,"type":"page"}{"title":"Coucou","id":12566436,"type":"page"}{"title":"test","id":60773462,"type":"page"}{"title":"test","id":55056236,"type":"page"}{"title":"test 3","id":25800608,"type":"folder","content":[]}{"title":"test 2","id":87726355,"type":"page"}{"title":"miaou","id":22238962,"type":"page"}nullnull{"title":"tst","id":67670870,"type":"page"}nullnullnull{"title":"ok","id":57558536,"type":"page"}{"title":"oui","id":26774218,"type":"folder","content":[{"title":"ptet","id":25131771,"type":"page"}]}{"title":"ok","id":64063692,"type":"page"}{"title":"oui","id":48113241,"type":"page"}{"title":"ok","id":64063692,"type":"page"}{"title":"oui","id":48113241,"type":"page"}{"title":"ok","id":64063692,"type":"page"}null{"title":"ok","id":64063692,"type":"page"}{"title":"oui","id":48113241,"type":"page"}{"title":"aze","id":78460099,"type":"page"}{"title":"eee","id":99135296,"type":"page"}[{"title":"eee","id":99135296,"type":"page"},{"title":"Donn\u00e9es personnelles","type":"page","id":9874265},{"title":"Surveillance d'\u00c9tat","type":"page","id":2548968},{"title":"Censure","type":"page","id":87984},{"title":"R\u00e9seaux T\u00e9l\u00e9com","type":"page","id":26548}]{"title":"eee","id":99135296,"type":"page"}{"title":"Coucou le r\u00e8glement bis","id":54018548,"type":"page"}{"title":"test","id":79742834,"type":"folder","content":[]}{"title":"Coucou F\u00e9lix","id":28700177,"type":"page"}{"title":"techopopo","id":19906810,"type":"folder","content":[{"title":"marseille","id":42511278,"type":"page"}]}{"title":"oui","id":65198467,"type":"page"}
\ No newline at end of file
{"content":[{"title":"Accueil","type":"page","id":0,"content":null},{"title":"Veille","type":"folder","id":23512434,"content":[{"title":"ePrivacy","type":"folder","id":59683048,"content":[{"title":"Intro","type":"page","id":687421},{"title":"Parlement UE","type":"page","id":2954542},{"title":"Conseil UE","type":"page","id":987564}]},{"title":"LPM 2019","type":"page","id":546132},{"title":"Copyright","type":"folder","id":86938573,"content":[{"title":"Introduction","type":"page","id":546842},{"title":"Parlement UE","type":"page","id":298745},{"title":"Conseil UE","type":"page","id":7894561}]},{"title":"Charte","type":"page","id":68742}]},{"title":"Ressources","type":"folder","id":5938573,"content":[{"title":"Donn\u00e9es personnelles","type":"page","id":9874265},{"title":"Surveillance d'\u00c9tat","type":"page","id":2548968},{"title":"Censure","type":"page","id":87984},{"title":"R\u00e9seaux T\u00e9l\u00e9com","type":"page","id":26548}]}]}
\ No newline at end of file
body
{
margin: 0;
font-family: sans-serif;