aboutsummaryrefslogtreecommitdiff
path: root/public
diff options
context:
space:
mode:
Diffstat (limited to 'public')
-rw-r--r--public/css/foot.css26
-rw-r--r--public/css/head.css70
-rw-r--r--public/js/Input.js132
3 files changed, 146 insertions, 82 deletions
diff --git a/public/css/foot.css b/public/css/foot.css
index 38284e3..ed65666 100644
--- a/public/css/foot.css
+++ b/public/css/foot.css
@@ -79,16 +79,16 @@ footer .data > div
79 margin: 0 3px; 79 margin: 0 3px;
80}*/ 80}*/
81 81
82#footer_logo_img 82#footer_logo_content
83{ 83{
84 max-width: 288px; 84 max-width: 288px;
85 min-width: 150px; 85 min-width: 150px;
86} 86}
87@media screen and (max-width: 1000px) 87@media screen and (max-width: 800px)
88{ 88{
89 .footer .contact 89 footer .contact
90 { 90 {
91 width: 70px; 91 font-size: smaller;
92 } 92 }
93} 93}
94 94
@@ -119,10 +119,6 @@ footer .data > div
119 color: black; 119 color: black;
120 text-decoration: none; 120 text-decoration: none;
121} 121}
122.empty_admin_zone
123{
124 height: 70px;
125}
126.logged_in 122.logged_in
127{ 123{
128 /*height: 70px;*/ 124 /*height: 70px;*/
@@ -149,6 +145,20 @@ footer .data > div
149 background-color: yellow; 145 background-color: yellow;
150 border-radius: 4px; 146 border-radius: 4px;
151} 147}
148@media screen and (max-width: 550px){
149 .logged_in, .logged_in button
150 {
151 font-size: 96%;
152 }
153 .admin_buttons_zone
154 {
155 margin: 3px;
156 }
157}
158.empty_admin_zone
159{
160 height: 93px; /* 40 => 1 ligne, 70/64 => 2 lignes, 93/83 => 3 lignes */
161}
152.modif_mode 162.modif_mode
153{ 163{
154 background-color: #ffae1a; /* orange clair soupe de poisson */ 164 background-color: #ffae1a; /* orange clair soupe de poisson */
diff --git a/public/css/head.css b/public/css/head.css
index dab81a8..c178d3a 100644
--- a/public/css/head.css
+++ b/public/css/head.css
@@ -21,33 +21,24 @@ header
21{ 21{
22 max-height: 24px; 22 max-height: 24px;
23} 23}
24 24.header_additional_inputs
25{
26 display: flex;
27 flex-wrap: wrap;
28 justify-content: space-evenly;
29 align-items: center;
30 margin-top: 10px;
31}
25.header_content 32.header_content
26{ 33{
27 padding: 20px 0; 34 margin-top: 10px;
35 padding-bottom: 20px;
28 display: grid; 36 display: grid;
29 grid-template-columns: 1fr 1fr 1fr; 37 grid-template-columns: 1fr 1fr 1fr;
30 align-items: end; 38 align-items: end;
31} 39}
32/*.header_left_col 40/*.header_left_col
33{}*/ 41{}*/
34@media screen and (max-width: 1000px){
35 .header_content{
36 padding: 18px 0;
37 }
38}
39@media screen and (max-width: 450px){
40 .header_content
41 {
42 /*grid-template-columns: 1fr 2fr 1fr;*/
43 display: block;
44 padding: 18px;
45 }
46 #header_logo
47 {
48 display: none;
49 }
50}
51 42
52.header_center_col 43.header_center_col
53{ 44{
@@ -73,7 +64,7 @@ header h2
73header img 64header img
74{ 65{
75 vertical-align: bottom; /* supprime espace sous l'image */ 66 vertical-align: bottom; /* supprime espace sous l'image */
76 max-width: 150px; 67 max-width: 180px;
77 max-height: 100px; 68 max-height: 100px;
78} 69}
79header a 70header a
@@ -83,13 +74,46 @@ header a
83} 74}
84/*.header_right_col 75/*.header_right_col
85{}*/ 76{}*/
86#header_social img 77#header_social
78{
79 display: flex;
80 justify-content: center;
81}
82#header_social_content img
87{ 83{
88 width: 28px; 84 width: 28px;
89 background-color: rgba(255, 255, 255, 0.7); 85 background-color: #ffffffb3;
90 border-radius: 50%; 86 border-radius: 50%;
91} 87}
92#header_social img:hover 88
89#header_social_content img:hover
93{ 90{
94 background-color: yellow; 91 background-color: yellow;
92}
93#header_social_input
94{
95 background-color: #ffffff7f;
96 border-radius: 10px;
97 padding: 5px;
98}
99
100@media screen and (max-width: 1000px){
101 .header_content{
102 padding: 15px 0;
103 }
104 header img
105 {
106 max-width: 160px;
107 }
108}
109@media screen and (max-width: 500px){
110 .header_content
111 {
112 display: block;
113 padding: 10px;
114 }
115 #header_logo
116 {
117 display: none;
118 }
95} \ No newline at end of file 119} \ No newline at end of file
diff --git a/public/js/Input.js b/public/js/Input.js
index 0b6912b..9a131c8 100644
--- a/public/js/Input.js
+++ b/public/js/Input.js
@@ -1,96 +1,126 @@
1class Input{ 1class InputToggler{
2 constructor(name){ 2 constructor(name, options = {}){
3 this.name = name; 3 this.name = name;
4 /*const name_array = name.split('_');
5 this.node = name_array[0];
6 this.what = name_array[1];*/
7 this.parent = document.getElementById(name); 4 this.parent = document.getElementById(name);
5
6 // ids alternatifs optionnels
7 this.content_elem = this.parent.querySelector(options.content_selector || `#${name}_content`);
8 this.input_elem = this.parent.querySelector(options.input_selector || `#${name}_input`);
9 this.open_elem = this.parent.querySelector(options.open_selector || `#${name}_open`);
10 this.submit_elem = this.parent.querySelector(options.submit_selector || `#${name}_submit`);
11 this.cancel_elem = this.parent.querySelector(options.cancel_selector || `#${name}_cancel`);
12
13 // balises à ne pas gérer (fonctionne mais inutilisé pour l'instant)
14 this.ignored_tags = {
15 has_content: options.has_content !== false, // => true sauf si le paramètre vaut false
16 has_input: options.has_input !== false,
17 has_open_button: options.has_open_button !== false,
18 has_submit_button: options.has_submit_button !== false,
19 has_cancel_button: options.has_cancel_button !== false
20 }
8 } 21 }
9 open(){ 22 open(){
10 this.parent.querySelector('#' + this.name + '_content').classList.add('hidden'); 23 this.toggleVisibility(true);
11 this.parent.querySelector('#' + this.name + '_input').classList.remove('hidden');
12 this.parent.querySelector('#' + this.name + '_open').classList.add('hidden');
13 this.parent.querySelector('#' + this.name + '_submit').classList.remove('hidden');
14 this.parent.querySelector('#' + this.name + '_cancel').classList.remove('hidden');
15 } 24 }
16 close(){ 25 close(){
17 this.parent.querySelector('#' + this.name + '_content').classList.remove('hidden'); 26 this.toggleVisibility(false);
18 this.parent.querySelector('#' + this.name + '_input').classList.add('hidden'); 27 }
19 this.parent.querySelector('#' + this.name + '_open').classList.remove('hidden'); 28 toggleVisibility(show_input = false){
20 this.parent.querySelector('#' + this.name + '_submit').classList.add('hidden'); 29 // avec && si la partie de gauche est "false", on traite la partie de droite
21 this.parent.querySelector('#' + this.name + '_cancel').classList.add('hidden'); 30 // ?. est l'opérateur de chainage optionnel
31 this.ignored_tags.has_content && this.content_elem.classList.toggle('hidden', show_input);
32 this.ignored_tags.has_input && this.input_elem.classList.toggle('hidden', !show_input);
33 this.ignored_tags.has_open_button && this.open_elem.classList.toggle('hidden', show_input);
34 this.ignored_tags.has_submit_button && this.submit_elem.classList.toggle('hidden', !show_input);
35 this.ignored_tags.has_cancel_button && this.cancel_elem.classList.toggle('hidden', !show_input);
22 } 36 }
23 cancel(){ 37 cancel(){
24 this.close(); 38 this.close();
25 } 39 }
26} 40}
27 41
28class InputFile extends Input{ 42class InputText extends InputToggler{
43 constructor(name, options = {}){
44 super(name, options);
45 this.fetch_endpoint = options.endpoint || 'index.php';
46 this.fetch_key = options.fetch_key || 'head_foot_text';
47 }
29 submit(){ 48 submit(){
30 const file = this.parent.querySelector('#' + this.name + '_input').files[0]; 49 fetch(this.fetch_endpoint + '?' + this.fetch_key + '=' + this.name, {
31 if(!file){ 50 method: 'POST',
32 console.error("Erreur: aucun fichier sélectionné."); 51 headers: { 'Content-Type': 'application/json' },
33 toastNotify("Erreur: aucun fichier sélectionné."); 52 body: JSON.stringify({new_text: this.input_elem.value})
34 return;
35 }
36 const form_data = new FormData();
37 form_data.append('file', file);
38
39 fetch('index.php?head_foot_image=' + this.name, {
40 method: 'POST', // apparemment il faudrait utiliser PUT
41 body: form_data
42 }) 53 })
43 .then(response => response.json()) 54 .then(response => response.json())
44 .then(data => { 55 .then(data => {
45 if(data.success){ 56 if(data.success){
46 // cas particuliers 57 this.content_elem.innerHTML = this.input_elem.value;
47 if(this.name === 'head_favicon'){
48 const link = document.querySelector('link[rel="icon"]');
49 link.type = data.mime_type;
50 link.href = data.location;
51 }
52 else if(this.name === 'header_background'){
53 document.querySelector('header').style.backgroundImage = "url('" + data.location + "')";
54 }
55
56 this.parent.querySelector('#' + this.name + '_content').src = data.location;
57 this.close(); 58 this.close();
58 } 59 }
59 else{ 60 else{
60 console.error("Erreur: le serveur n'a pas enregistré l'image'."); 61 console.error("Erreur: le serveur n'a pas enregistré le nouveau texte.");
61 } 62 }
62 }) 63 })
63 .catch(error => { 64 .catch(error => {
64 console.error('Erreur:', error); 65 console.error('Erreur:', error);
65 }); 66 });
66 } 67 }
68 cancel(){
69 this.input_elem.value = this.content_elem.innerHTML;
70 super.cancel();
71 }
67} 72}
68 73
69class InputText extends Input{ 74class InputFile extends InputToggler{
75 constructor(name, options = {}){
76 super(name, options);
77 this.fetch_endpoint = options.endpoint || 'index.php';
78 this.fetch_key = options.fetch_key || 'head_foot_image';
79 }
70 submit(){ 80 submit(){
71 const new_text = this.parent.querySelector('#' + this.name + '_input').value; 81 const file = this.input_elem.files[0];
82 if(!file){
83 console.error("Erreur: aucun fichier sélectionné.");
84 toastNotify("Erreur: aucun fichier sélectionné.");
85 return;
86 }
87 const form_data = new FormData();
88 form_data.append('file', file);
72 89
73 fetch('index.php?head_foot_text=' + this.name, { 90 fetch(this.fetch_endpoint + '?' + this.fetch_key + '=' + this.name, {
74 method: 'POST', 91 method: 'POST', // apparemment il faudrait utiliser PUT
75 headers: { 'Content-Type': 'application/json' }, 92 body: form_data
76 body: JSON.stringify({new_text: new_text})
77 }) 93 })
78 .then(response => response.json()) 94 .then(response => response.json())
79 .then(data => { 95 .then(data => {
80 if(data.success){ 96 if(data.success){
81 this.parent.querySelector('#' + this.name + '_content').innerHTML = new_text; 97 this.onSuccess(data);
82 this.close(); 98 this.close();
83 } 99 }
84 else{ 100 else{
85 console.error("Erreur: le serveur n'a pas enregistré le nouveau texte."); 101 console.error("Erreur: le serveur n'a pas enregistré l'image'.");
86 } 102 }
87 }) 103 })
88 .catch(error => { 104 .catch(error => {
89 console.error('Erreur:', error); 105 console.error('Erreur:', error);
90 }); 106 });
91 } 107 }
92 cancel(){ // surcharge 108 onSuccess(data){
93 this.parent.querySelector('#' + this.name + '_input').value = this.parent.querySelector('#' + this.name + '_content').innerHTML; 109 this.content_elem.src = data.location;
94 this.close();
95 } 110 }
111}
112
113class InputFileFavicon extends InputFile{
114 onSuccess(data){
115 const link = document.querySelector('link[rel="icon"]');
116 link.type = data.mime_type;
117 link.href = data.location;
118 super.onSuccess(data);
119 }
120}
121class InputFileHeaderBackground extends InputFile{
122 onSuccess(data){
123 document.querySelector('header').style.backgroundImage = `url('${data.location}')`;
124 super.onSuccess(data);
125 }
96} \ No newline at end of file 126} \ No newline at end of file