
@ -0,0 +1,23 @@
|
||||
[(#REM) liste toutes les configurations trouvees dans le texte de l'article ] |
||||
<B_a> |
||||
|
||||
<BOUCLE_a(ARTICLES){id_article=#ENV*{id_article}}{tout}> |
||||
|
||||
[(#SET{jeux, [(#TEXTE*|jeux_isoler_les_jeux)]})] |
||||
|
||||
<B_afficher> |
||||
[(#SET{titre, [(#ENV*{titre,#GRAND_TOTAL|singulier_ou_pluriel{jeu:info_1_jeu_inline,jeu:info_nb_jeux_inline}})]})] |
||||
#BOITE_OUVRIR{'', 'info'} |
||||
[(#BOITE_OUVRIR{[(#CHEMIN_IMAGE{jeux-edit-24.png}|balise_img{'',cadre-icone})][(#GET{titre}|wrap{'<h3>'})],'simple'})] |
||||
|
||||
<BOUCLE_afficher(DATA){source tableau,#GET{jeux}}> |
||||
#SET{valeur, #VALEUR|echappe_retour} |
||||
<h3>##COMPTEUR_BOUCLE.[(#GET{valeur}|titre_jeu)]</h3> |
||||
[<div class ="jeux_decaler_config">(#GET{valeur}|jeux_trouver_configuration_complete)</div>] |
||||
</BOUCLE_afficher> |
||||
</B_afficher> |
||||
|
||||
</BOUCLE_a> |
||||
#BOITE_FERMER |
||||
#BOITE_FERMER |
||||
</B_a> |
After Width: | Height: | Size: 195 B |
After Width: | Height: | Size: 124 B |
After Width: | Height: | Size: 124 B |
After Width: | Height: | Size: 124 B |
After Width: | Height: | Size: 124 B |
After Width: | Height: | Size: 124 B |
After Width: | Height: | Size: 124 B |
After Width: | Height: | Size: 106 B |
After Width: | Height: | Size: 93 B |
After Width: | Height: | Size: 136 B |
After Width: | Height: | Size: 111 B |
After Width: | Height: | Size: 111 B |
After Width: | Height: | Size: 107 B |
@ -0,0 +1,254 @@
|
||||
<?php |
||||
if (!defined("_ECRIRE_INC_VERSION")) return; |
||||
#---------------------------------------------------# |
||||
# Plugin : jeux # |
||||
# Auteur : Patrice Vanneufville, 2020 # |
||||
# Contact : patrice¡.!vanneufville¡@!laposte¡.!net # |
||||
# Licence : GPL # |
||||
#--------------------------------------------------------------------------# |
||||
# Documentation : https://contrib.spip.net/Des-jeux-dans-vos-articles # |
||||
#--------------------------------------------------------------------------# |
||||
/* |
||||
|
||||
Insere des parties d'echecs dans vos articles ! |
||||
----------------------------------------------- |
||||
https://github.com/baptx/connect-points/ |
||||
https://drawcode.eu/projects/connect-points/ |
||||
|
||||
Attention : utilisation d'une librairie externe : |
||||
------------------------------------------------- |
||||
|
||||
separateur obligatoire : [gauche] [droite] |
||||
separateur optionnel : [solution] [config] |
||||
parametres de configurations par defaut : |
||||
Couleur lignes = rouge |
||||
Couleur erreurs = noir |
||||
Espace vertical = 40 |
||||
Espace horizontal = 140 |
||||
Marge horizontale = 30 |
||||
Transparence = non |
||||
Recadre auto = non |
||||
Compteur = non |
||||
Aléatoire = non |
||||
Tout relier = oui |
||||
|
||||
Exemple de syntaxe dans l'article : |
||||
----------------------------------- |
||||
|
||||
<jeux> |
||||
[config] |
||||
Compteur = oui |
||||
Aléatoire = oui |
||||
[titre] |
||||
Traductions Français/Allemand |
||||
[gauche] |
||||
la voiture |
||||
l'ordinateur |
||||
l'horloge |
||||
l'école |
||||
le vélo |
||||
les devoirs |
||||
les amis |
||||
la mer |
||||
les vacances |
||||
la casquette |
||||
[droite] |
||||
die Uhr |
||||
das Fahrrad |
||||
das Meer |
||||
der Computer |
||||
die Schule |
||||
die Hausaufgaben |
||||
die Ferien |
||||
die Freunde |
||||
die Mütze |
||||
das Auto |
||||
[solution] |
||||
10,4,1,5,2,6,8,3,7,9 |
||||
</jeux> |
||||
|
||||
Deux solutions pour afficher un jeu de points e relier : |
||||
- code inline du jeu dans un article |
||||
- modele <jeuXXX> : jeu cree grace a l'interface du plugin |
||||
|
||||
*/ |
||||
|
||||
// configuration par defaut : jeux_{mon_jeu}_init() |
||||
function jeux_relier_init() { |
||||
return " |
||||
Couleur lignes = rouge |
||||
Couleur erreurs = noir |
||||
Espace vertical = 40 |
||||
Espace horizontal = 140 |
||||
Marge horizontale = 30 |
||||
Transparence = non |
||||
Recadre auto = non |
||||
Compteur = non |
||||
Aléatoire = non |
||||
Tout relier = oui |
||||
"; |
||||
} |
||||
|
||||
define('_relier_balise', '@@RELIER@@'); |
||||
|
||||
// liste des libelles (textes, images ou autres) à relier |
||||
function relier_liste_mots($texte) { |
||||
// tenir compte des retours à la ligne manuels |
||||
$texte = preg_replace(",[\n\r]+_ +,s", "<br class='manualbr' />", $texte); |
||||
return array_filter(preg_split('/[\r\n]+/', trim($texte))); |
||||
} |
||||
|
||||
// le jeux est inséré à la place de la première balise |
||||
function relier_placer_jeu($html, $jeu){ |
||||
if (strpos($html, _relier_balise) !== false) |
||||
$html = substr_replace($html, $jeu, strpos($html, _relier_balise), strlen(_relier_balise)); |
||||
return str_replace(_relier_balise, '', $html); |
||||
} |
||||
|
||||
// tente de sécuriser les données à relier |
||||
function relier_safe($val) { |
||||
if(!$val) return ''; |
||||
// si c'est un texte simple, on traite les raccourcis sans paragraphage |
||||
if(strpos('</', $val)===false) |
||||
$val = PtoBR(traiter_raccourcis(trim($val))); |
||||
// $val = preg_replace(',<br[^>]*>,', ' ', $val); |
||||
return $val; |
||||
} |
||||
|
||||
// fonction principale : jeux_{mon_jeu}() |
||||
function jeux_relier($texte, $indexJeux, $form = true) { |
||||
$titre = $html = $gauche = $droite = $ordreGauche = $ordreDroite = $newDroite = $newGauche = $solution = $idImage = false; |
||||
// parcourir tous les #SEPARATEURS |
||||
$tableau = jeux_split_texte('relier', $texte); |
||||
foreach($tableau as $i => $valeur) if ($i & 1) { |
||||
if ($valeur==_JEUX_TITRE) $titre = $tableau[$i+1]; |
||||
elseif ($valeur==_JEUX_GAUCHE) { $html .= _relier_balise; $gauche = relier_liste_mots($tableau[$i+1]); } |
||||
elseif ($valeur==_JEUX_DROITE) { $html .= _relier_balise; $droite = relier_liste_mots($tableau[$i+1]); } |
||||
elseif ($valeur==_JEUX_SOLUTION) $solution = jeux_liste_mots($tableau[$i+1], false); |
||||
|
||||
elseif ($valeur==_JEUX_TEXTE) $html .= $tableau[$i+1]; |
||||
elseif ($valeur==_JEUX_COPYRIGHT) $html .= '<div class="jeux_copyright">' . $tableau[$i+1] . '</div>'; |
||||
} |
||||
|
||||
// cas particulier : une seule image de fond |
||||
// syntaxe : [->imgNNN] (nbPtsG, nbPtsD) (offserX, offset Y) |
||||
// exemple : [->img1341] (7, 7) (25, 15) |
||||
$nbG = $gauche ? count($gauche) : 0; |
||||
$nbD = $droite ? count($droite) : 0; |
||||
if($uneImage = ($nbG + $nbD === 1)) { |
||||
$imageFond = $nbG ? $gauche[0] : $droite[0]; |
||||
$uneImage = preg_match('@^(?:image|doc|emb|img)(\d+)[^\d]+(\d+)[^\d]+(\d+)[^\d]+([\d\.]+)%[^\d]+([\d\.]+)%[^\d]+([\d\.]+)%[^\d]+([\d\.]+)%$@', trim($imageFond), $regs); |
||||
if($uneImage) { |
||||
list(, $idImage, $nbGauche, $nbDroite, $distanceX, $distanceY, $pixelsGauche, $pixelsHaut) = $regs; |
||||
|
||||
$gauche = array_fill(0, $nbGauche, ''); |
||||
$droite = array_fill(0, $nbDroite, ''); |
||||
//$uneImage = $lienImage . join('|', $regs); |
||||
jeux_config_set('espaceHorizontal', $distanceX); |
||||
jeux_config_set('espaceVertical', $distanceY); |
||||
jeux_config_set('margeHorizontale', $pixelsGauche); |
||||
jeux_config_set('margeVerticale', $pixelsHaut); |
||||
} |
||||
} |
||||
|
||||
if(!$uneImage && (!$gauche || !$droite)) |
||||
return _L('ERREUR de syntaxe, il manque : ') . (!$droite?_L("la liste de droite"):_L("la liste de gauche")); |
||||
if(!$solution) |
||||
$solution = range(1, min(count($gauche), count($droite))); |
||||
if($ordreGaucheOK = (strpos($solution[0], '=') !== false)) { |
||||
// syntaxe : [solution] 1=3, 2=2, 3=2, 4=5, 5=4 |
||||
foreach($solution as $i => $val) { |
||||
$arr = explode('=', $val); |
||||
$ordreGauche[$i] = strval(trim($arr[0])); |
||||
$ordreDroite[$i] = strval(trim($arr[1])); |
||||
} |
||||
} else { |
||||
// syntaxe : [solution] 1, 2, 3, 4, 5 |
||||
foreach($solution as $i=>$val) $ordreDroite[$i] = strval($val); |
||||
} |
||||
foreach($gauche as $i => &$val) { |
||||
if(!$ordreGaucheOK) $ordreGauche[$i] = $i + 1; |
||||
$val = array( |
||||
'index' => $i + 1, |
||||
'data' => "<div>" . relier_safe($val) . "</div>", |
||||
); |
||||
} |
||||
foreach($droite as $i => &$val) { |
||||
$val = array( |
||||
'index' => $i + 1, |
||||
'data' => "<div>" . relier_safe($val) . "</div>", |
||||
); |
||||
} |
||||
|
||||
if (jeux_config('aleatoire')) { |
||||
shuffle($gauche); shuffle($droite); |
||||
foreach ($gauche as $i => &$val) $newGauche[$i + 1] = $val['index']; |
||||
foreach ($droite as $i => &$val) $newDroite[$i + 1] = $val['index']; |
||||
foreach ($ordreGauche as &$val) $val = array_search($val, $newGauche); |
||||
foreach ($ordreDroite as &$val) $val = array_search($val, $newDroite); |
||||
} |
||||
foreach ($gauche as &$val) $val = $val['data']; |
||||
foreach ($droite as &$val) $val = $val['data']; |
||||
$gauche = join('', $gauche); |
||||
$droite = join('', $droite); |
||||
|
||||
$tete = '<div class="jeux_cadre relier">'; |
||||
if ($titre) $tete .= '<div class="jeux_titre relier_titre">' . $titre . '<hr /></div>'; |
||||
|
||||
// recuperation du fond 'jeux/relier.html' en protegeant le javascript |
||||
// traitement ulterieur sur les colonnes droite et gauche |
||||
include_spip('public/assembler'); |
||||
$solution = protege_js_modeles(recuperer_fond('modeles/relier', array( |
||||
'indexJeux' => $indexJeux, |
||||
'id_jeu' => _request('id_jeu'), |
||||
'colGauche' => '@@GAUCHE@@', |
||||
'colDroite' => '@@DROITE@@', |
||||
'ordreGauche' => base64_encode(join('/', $ordreGauche)), |
||||
'ordreDroite' => base64_encode(join('/', $ordreDroite)), |
||||
'couleurLignes' => jeux_rgb(jeux_config('couleurLignes')), |
||||
'couleurErreurs' => jeux_rgb(jeux_config('couleurErreurs')), |
||||
'espaceVertical' => floatval(jeux_config('espaceVertical')), |
||||
'espaceHorizontal' => floatval(jeux_config('espaceHorizontal')), |
||||
'margeHorizontale' => floatval(jeux_config('margeHorizontale')), |
||||
'margeVerticale' => floatval(jeux_config('margeVerticale')), |
||||
'toutRelier' => floatval(jeux_config('toutRelier')), |
||||
'compteur' => intval(jeux_config('compteur')), |
||||
'imageFond' => $idImage, |
||||
))); |
||||
|
||||
// placer les boutons à la fin |
||||
$solution = explode('<!-- Boutons -->', $solution, 2); |
||||
// mise en clair des images et autres modeles échappés |
||||
$solution[0] = echappe_retour($solution[0]); // jeux lui-même et tous ses textes |
||||
$gauche = echappe_retour($gauche); // donnees colonne de gauche |
||||
$droite = echappe_retour($droite); // donnees colonne de droite |
||||
// config avec demande de transparence des images sur un fond de couleur ? |
||||
if($couleur = jeux_config('transparence')) { |
||||
$couleur = jeux_rgb($couleur, false); |
||||
$solution[0] = filtrer('image_fond_transparent', $solution[0], $couleur); |
||||
$gauche = filtrer('image_fond_transparent', $gauche, $couleur); |
||||
$droite = filtrer('image_fond_transparent', $droite, $couleur); |
||||
} |
||||
$hauteurMaxGD = intval(jeux_config('espaceVertical')); |
||||
// on reduit l'image au plus petit rectangle possible ? |
||||
if(jeux_config('recadreAuto')) { |
||||
$solution[0] = filtrer('image_recadre_mini', $solution[0]); |
||||
$gauche = filtrer('image_recadre_mini', $gauche); |
||||
$droite = filtrer('image_recadre_mini', $droite); |
||||
// Format : nn% |
||||
if(preg_match(',(\d+)%,', jeux_config('recadreAuto'), $regs)) |
||||
$hauteurMaxGD = round($hauteurMaxGD * $regs[1] / 100); |
||||
} |
||||
|
||||
$gauche = filtrer('image_reduire', $gauche, 0, $hauteurMaxGD); |
||||
$droite = filtrer('image_reduire', $droite, 0, $hauteurMaxGD); |
||||
|
||||
$solution[0] = str_replace(array('@@GAUCHE@@', '@@DROITE@@'), array($gauche, $droite), $solution[0]); |
||||
|
||||
// nouvel échappement |
||||
$html = relier_placer_jeu($html, code_echappement($solution[0])) . $solution[1]; |
||||
return $tete . $html . '</div>'; |
||||
|
||||
} |
||||
|
||||
?> |
@ -0,0 +1,52 @@
|
||||
[(#REM) paddingX du canvas: 30px à gauche + 30px à droite ] |
||||
#SET{widthCanvas, 220} |
||||
[(#ENV*{imageFond}|non) |
||||
#SET{2xPaddingX, #ENV{margeHorizontale, 30}|intval|mult{2}} |
||||
#SET{widthCanvas, #ENV{espaceHorizontal, 140}|intval|plus{#GET{2xPaddingX}}} |
||||
] |
||||
#SET{toutRelier, #ENV{toutRelier}|?{1,0}} |
||||
<div id="relierDataL#ENV{indexJeux}">#ENV*{colGauche}</div> |
||||
<div id="relierDataR#ENV{indexJeux}">#ENV*{colDroite}</div> |
||||
[<div class="relierImageFond" id="ImageFond#ENV{indexJeux}" >#MODELE{image,id=#ENV*{imageFond}}</div>(#ENV*{imageFond}|oui)] |
||||
<div class="relierInfoTop"> |
||||
<div id="exo#ENV{indexJeux}"></div> |
||||
</div> |
||||
<div id="relierContent#ENV{indexJeux}" class="relierContent"> |
||||
<div class = "relierContent1"> |
||||
<div id="relierDivGauche#ENV{indexJeux}" class="relierDivGauche relierDivColonne"></div> |
||||
</div> |
||||
<div class = "relierContent2"> |
||||
<div> |
||||
<div id="AlertContainer#ENV{indexJeux}" class="relierAlertContainer"></div> |
||||
<canvas id="canvas#ENV{indexJeux}" class="relierCanvas" |
||||
width="#GET{widthCanvas}" height="440"> |
||||
<!-- message pour les navigateurs ne supportant pas encore canvas --> |
||||
Votre navigateur ne supporte pas l'élément canvas. |
||||
</canvas> |
||||
</div> |
||||
</div> |
||||
<div class = "relierContent3"> |
||||
<div id="relierDivDroite#ENV{indexJeux}" class="relierDivDroite relierDivColonne"></div> |
||||
</div> |
||||
</div> |
||||
<!-- Boutons --> |
||||
<div class="relierAvantBoutons"></div> |
||||
<div class="relierBoutons"><div> |
||||
<button id="del#ENV{indexJeux}" class="jeux_bouton ToolBtn"><img src="#CHEMIN{img/relier/scissors_ready.gif}"></button> |
||||
<button id="relierBack#ENV{indexJeux}" class="jeux_bouton RestoreBtn"><img src="#CHEMIN{img/relier/undo.gif}"></button> |
||||
<button id="relierForward#ENV{indexJeux}" class="jeux_bouton RestoreBtn"><img src="#CHEMIN{img/relier/redo.gif}"></button> |
||||
<button id="connection#ENV{indexJeux}" class="jeux_bouton relierConnection">Corriger</button> |
||||
</div> |
||||
<div id="count#ENV{indexJeux}" class="relierCount"></div> |
||||
</div> |
||||
<div id="infoBottom#ENV{indexJeux}" class="relierInfoBottom"></div> |
||||
<script> |
||||
relierDraw_create(true, "#ENV{indexJeux}", |
||||
"relierDataL#ENV{indexJeux}", "relierDataR#ENV{indexJeux}", |
||||
atob("#ENV*{ordreGauche}").split('/'), atob("#ENV*{ordreDroite}").split('/'), |
||||
"#CHEMIN{img/relier/}", "#ENV{couleurLignes, '#FF0000'}", "#ENV{couleurErreurs, '#000000'}", |
||||
"#ENV*{espaceHorizontal, 140}/#ENV*{espaceVertical, 40}/#ENV*{margeHorizontale, 30}/#ENV*{margeVerticale, 20}/#GET{toutRelier}", |
||||
#ENV{compteur, 0} |
||||
); |
||||
</script> |
||||
<noscript>Vous devez avoir Javascript activé pour utiliser ce module</noscript> |
@ -0,0 +1,145 @@
|
||||
.jeux_cadre .relierCanvas { /* modifier la position du clic du curseur personnalisé */ |
||||
cursor: url(../img/relier/pen_red_ff0000.gif)0 20, auto; |
||||
} |
||||
|
||||
.relierInfoTop, .relierInfoBottom { /* marge encadrant les blocs div principaux */ |
||||
margin: 20px; |
||||
} |
||||
|
||||
.relierContent { |
||||
text-align: center; |
||||
} |
||||
|
||||
.relierInfoTop { display: none; } |
||||
|
||||
.relierInfoBottom { /* espace entre le contenu (canvas + texte) et les informations du bas du module pour le mode administration */ |
||||
position: relative; |
||||
top: 45px; |
||||
} |
||||
|
||||
.jeux_cadre .relierContent > div { /* afficher les colonnes de blocs à la suite, sur une ligne */ |
||||
display: inline-block; |
||||
vertical-align: top; |
||||
} |
||||
|
||||
.relierContent1, .relierContent3 { /* les 2 colonnes entourant le canvas du jeu */ |
||||
/* max-width: 33%; */ |
||||
} |
||||
|
||||
.jeux_cadre .relierDivGauche { /* espace entre le bloc de texte gauche et le bloc contenant le canvas */ |
||||
/* margin-right: 50px; */ |
||||
} |
||||
|
||||
.jeux_cadre .relierDivDroite { /* espace entre le bloc de texte de droite et le bloc contenant le canvas */ |
||||
/* margin-left: 50px; */ |
||||
} |
||||
|
||||
.relierDivColonne .relierElement { /* style et position du texte pour les balises div, lorsque l'utilisateur fait un exercice */ |
||||
display: flex; |
||||
flex-direction: column; |
||||
justify-content: center; |
||||
font-family: sans-serif; /* sans-serif: police ayant une bonne compatibilité entre navigateurs (arial: décalage 1px suivant la propriété font-size) */ |
||||
} |
||||
|
||||
.relierDivColonne dl.spip_documents, .relierDivColonne img { |
||||
margin: 0; |
||||
border: 0; |
||||
padding: 0; |
||||
} |
||||
.relierDivColonne dl.spip_documents dt:nth-child(2) { |
||||
display: none; /* pas de titre sur les images eventuelles */ |
||||
} |
||||
|
||||
.relierCount { |
||||
float: right; |
||||
font-size: smaller; |
||||
} |
||||
|
||||
.inputText > input { /* style et position du texte pour les balises input, lorsque l'utilisateur créé ou modifie un exercice */ |
||||
height: 18px; /* nécessaire de préciser la taille pour avoir la même marge suivant les navigateurs */ |
||||
margin-bottom: 16px; |
||||
position: relative; |
||||
top: 25px; |
||||
} |
||||
|
||||
.relier .relierBoutons div { |
||||
display: flex; |
||||
} |
||||
|
||||
.relier .relierBoutons { |
||||
text-align: center; |
||||
} |
||||
|
||||
.relier .relierAvantBoutons { |
||||
border-top: 2px solid lightgrey; |
||||
margin: 1em 15%; |
||||
} |
||||
|
||||
.relier .ToolBtn { /* épaisseur et position du bouton d'outils ciseaux pour supprimer un tracé */ |
||||
padding: 3px 6px; |
||||
margin: auto 50px auto auto; |
||||
} |
||||
|
||||
.relier .RestoreBtn { |
||||
/* épaisseur et position des boutons permettant de restaurer un tracé en avant/arrière */ |
||||
padding: 3px 3px; |
||||
margin: auto 5px auto; |
||||
} |
||||
|
||||
.relier .relierConnection { /* position du bouton de connexion corriger ou envoyer suivant l'utilisation du module */ |
||||
margin: auto auto auto 50px; |
||||
} |
||||
|
||||
.inputRemove { /* bouton (croix rouge) permettant de supprimer les champs en mode administration */ |
||||
padding: 0px 0px 0px 0px; |
||||
background: none; |
||||
border: 0px; |
||||
position: absolute; /* position absolute permet d'éviter d'avoir des décalages entre éléments */ |
||||
margin-top: 30px; /* utiliser margin-top et margin-left au lieu de top et left pour commencer depuis le haut-gauche de la page */ |
||||
margin-left: 5px; |
||||
} |
||||
|
||||
.relierAlertContainer { |
||||
z-index:99; /* z-index permet de donner une priorité sur l'affichage des éléments (div au dessus des tags input) */ |
||||
position: absolute; |
||||
margin-top: 50px; |
||||
} |
||||
.relierAlertBox { /* style de la boîte de dialogue HTML/CSS */ |
||||
background-color: white; |
||||
border-style: solid; |
||||
border-width: 1px; |
||||
padding: 15px 20px 5px 20px; |
||||
max-width: 500px; /* continuer le message sur une nouvelle ligne si on atteint une boîte de dialogue de plus de 500 pixels de large */ |
||||
text-align: center; |
||||
} |
||||
|
||||
.relier .AlertButton { /* style du bouton par défaut de la boîte de dialogue HTML/CSS */ |
||||
width: 75px; |
||||
} |
||||
|
||||
.relier .extraAdmin { /* positionnement du bloc textarea + coordonnées canvas + bouton reset (utilisation de l'option debug) */ |
||||
position: absolute; |
||||
left: 550px; |
||||
top: 15px; |
||||
} |
||||
|
||||
.relier .extraUser { /* bloc extra pour l'utilisateur classique */ |
||||
position: absolute; |
||||
top: -20px; |
||||
} |
||||
|
||||
.jeux_cadre .relierCoordonnees { /* décalage positionnement pour la balise input text des coordonnées canvas */ |
||||
position: relative; |
||||
top: -5px; |
||||
left: 15px; |
||||
} |
||||
|
||||
.jeux_cadre .relierReset { /* décalage positionnement pour la balise input button du bouton reset */ |
||||
position: relative; |
||||
top: -35px; |
||||
left: -50px; |
||||
} |
||||
|
||||
.jeux_cadre .relierImageFond { |
||||
display: none; |
||||
} |