2
votes

Comment puis-je modifier une image en fonction d'une sélection déroulante?

Je m'excuse si vous avez déjà répondu à cette question, j'ai essayé de faire une recherche, mais je n'ai rien trouvé qui m'a aidé à résoudre ce problème. Sur le problème!

Je tente de mettre à jour une feuille de personnage de la communauté pour Roll20. La feuille utilise à la fois HTLM et Javascript. J'essaye de mettre en place la feuille de sorte que lorsqu'un joueur sélectionne le type de puissance du sort qu'il utilise (pensez école de sorts de D&D), il place une icône différente sur le bouton du sort.

Les sorts sont contenus dans un composant de bouton HTML d'un conteneur repeating_spell conçu pour créer de nouveaux boutons uniques pour chaque sort.

Je parviens à faire en sorte que l'image soit une image statique, la même image quel que soit le type de puissance, mais je ne sais pas comment modifier dynamiquement la balise HTML img en fonction du type de puissance.

J'ai récemment réalisé que le site pour lequel je conçois cette feuille de personnage n'autorise pas l'indicateur d'id à l'intérieur la balise img. J'ai modifié mon code pour afficher le changement. J'essaie actuellement de le faire en utilisant le drapeau name =, et je ne suis pas sûr que jQuery le trouve car je ne reçois aucune image renvoyée. Voici le code actuel de ma balise img:

on("change:spellschool", function(eventinfo){
  getAttrs(["spellschool"], function(v) {
    var spell_school = spellschool.toLowerCase();
    if(spell_school === "biotic") {
      document.getElementById("powertype").src = "https://n7.world/images/spells/biotic.svg";
    }
    else if(spell_school === "combat") {
      document.getElementById("powertype").src = "https://n7.world/images/spells/combat.svg";
    }
    else if(spell_school === "tech") {
      document.getElementById("powertype").src = "https://n7.world/images/spells/tech.svg";
    }
    else {
      return;
    }
  });
});

avec les références JS / jQuery appropriées définies dans une boucle if / else qui vérifie l'attribut défini par la liste déroulante en utilisant ce qui suit code:

<img name="powertype" src="#" style="width: 15px; height: 15px; padding: 2px;">

Cependant, lorsque le code ci-dessus est défini, il renvoie simplement une image vide avec un remplissage.


4 Réponses :


3
votes

Vous avez des erreurs de syntaxe dans votre JS -

Citation de début manquante à la ligne 6:
Parenthèses de fin manquantes à la ligne 10:

Autre que cela .. Je l'ai simplifié pour vous:

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<img id="powertype" src="#" style="width: 15px; height: 15px; padding: 2px;">

<select id="spellschool">
<option>Select one</option>
<option value="biotic">biotic</option>
<option value="combat">combat</option>
<option value="tech">tech</option>
</select>
$('#spellschool').on('change', function(eventinfo){


    if(this.value == "biotic") {
        document.getElementById("powertype").src =
            "https://n7.world/images/spells/biotic.svg";
    } else if(this.value === "combat") {
        document.getElementById("powertype").src =
            "https://n7.world/images/spells/combat.svg";
    } else if(this.value === "tech") {
        document.getElementById("powertype").src =
            "https://n7.world/images/spells/tech.svg";
    } else {
        return;
    }
});


3 commentaires

Hey! Merci pour la réponse rapide. J'ai essayé votre code et il ne retire toujours pas l'image. En creusant un peu, je pense que c'est parce que Roll20 ne permet pas l'utilisation d'éléments id. J'ai essayé de changer l'img pour avoir name = "powertype" puis de changer le Javascript en getElementByName, mais cela ne semble pas aider ... Un autre conseil?


Essayez getElementsByName ("powertype") [0] . Plusieurs éléments sont autorisés à partager la même valeur dans leur attribut name (contrairement à l'attribut id ), vous devez donc tous les obtenir, puis spécifier le premier (en utilisant [0] ).


Donc, j'avais eu une pensée ... Je pense que la raison pour laquelle getElementByName ne fonctionne pas est parce que l'attribut powertype est dans chaque nouveau sort qui est créé et n'est pas assez unique. Je me demandais si une fonction forEach () pourrait me permettre d'y déposer la boucle if / else afin qu'elle vérifie chaque repeating_spell par spellid ...



1
votes

Je ne peux pas lier une image dans un extrait SO **, mais voici une solution à la vanille qui obtient le chemin vers l'image. La définition de l'attribut src d'un élément img égal à pathSpan.innerHTML fonctionne pour afficher un .png ou .jpg, donc à moins que . svg s se comportent différemment, cela devrait gérer votre cas d'utilisation.

<select id="dropdown">
  <option value="1">1</option>
  <option value="2">2</option>
  <option value="3">3</option>
</select>
<br />
<span>Path to image: </span><span id="imgPath">images/one</span>
const dropdown = document.getElementById("dropdown"),
      pathSpan = document.getElementById("imgPath");
dropdown.addEventListener("change", updateImage);

function updateImage(event){
  if(event.target.value == "1"){
    pathSpan.innerHTML = "images/one";
  }
  else if(event.target.value == "2"){
    pathSpan.innerHTML = "images/two";
  }
  else if(event.target.value == "3"){
    pathSpan.innerHTML = "images/three";
  }
  else{
    pathSpan.innerHTML = "";
  }
}

** Je m'assois corrigé. Le lien vers une image accessible au public sur le Web fonctionne bien, comme Zak l'a prouvé dans sa réponse. (En production, vous voudrez peut-être créer un lien vers une image stockée localement sur votre serveur à la place, afin que votre code ne puisse pas être brisé par des modifications sur un site externe.)


1 commentaires

Le problème avec ceci est que ce n'est pas quelque chose de stocké sur un serveur que je contrôle. Ce code est pour une feuille de personnage utilisée sur le site roll20.net. Le code doit donc se limiter à un grand nombre de leurs exigences. Comme aucune balise réservée comme head ou body, et aucun indicateur comme id, car ils ont besoin que les éléments soient uniques par feuille, car il est probable que plusieurs copies de cette page soient ouvertes car plusieurs joueurs utilisent tous des feuilles de personnage.



0
votes

Vous pouvez également faire de même avec Vanilla JS.

HTML:

const select = document.querySelector('#spellschool');
const img = document.querySelector('#powertype');

select.addEventListener('change', (e) => {

    img.src = `https://n7.world/images/spells/${e.target.value}.svg`

    console.log(e.target.value)
})

JS:

const select = document.querySelector('#spellschool');
const img = document.querySelector('#powertype');

select.addEventListener('change', () => {
    if (select.value === 'biotic') {
        img.src = 'https://n7.world/images/spells/biotic.svg'
    } else if (select.value === 'combat') {
        img.src = 'https://n7.world/images/spells/combat.svg'
    } else {
        img.src = 'https://n7.world/images/spells/tech.svg'
    }
})

Et voici un exemple encore meilleur

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>

    <select id='spellschool'>
        <option value="biotic">Biotic</option>
        <option value="combat">Combat</option>
        <option value="tech">Tech</option>
    </select>

    <img id="powertype" src="#" style="width: 150px; height: 150px; padding: 20px;">
    <script src="main.js"></script>
</body>
</html>

Où nous utilisons l'es6 `` (sacs à dos) pour modifier la valeur sélectionnée en une chaîne.


0 commentaires

0
votes

Les détails sont commentés dans la démo. Reportez-vous au Tutoriel JavaScript et formulaires . BTW, l'ID d'attribut est un aspect fondamental de JavaScript et DOM, et ne peut pas être ignoré si facilement par une API. Un identifiant doit être unique et je suppose que vous avez tenté d'attribuer un identifiant à plus de un élément d'où votre hypothèse sans équivoque que l'id "ne fonctionne pas" . Si pour une raison quelconque vous ne pouvez pas le faire fonctionner en coupant et en collant quelque chose (vous n'avez pas vraiment décrit comment vous implémentez le code) - essayez de changer tous les identifiants en nom. C'est un avantage de l'élément

est le L'API HTMLFormElement permet une association transparente entre l'identifiant et le nom (ils sont interchangeables dans un formulaire).

<form>
  <fieldset>
    <legend>Schools of Magic</legend>
    <select name='schools'>
      <option value='0' selected>Select a School</option>
      <option value='1'>Necromancy</option>
      <option value='2'>Invocation</option>
      <option value='3'>Abjuration</option>
      <option value='4'>Divination</option>
      <option value='5'>Illusion</option>
      <option value='6'>Transmutation</option>
      <option value='7'>Conjuration</option>
      <option value='8'>Enchantment</option>
    </select>
    <input name='images' src='https://i.ibb.co/StzKvdm/8.gif' type='image' width='220' height='220' data-idx='0'>
  </fieldset>
</form>
:root {
  font: 700 small-caps 3vw/2 'Tempus Sans ITC';
}

body {
  color: #fff;
  background: #000;
}

legend {
  font-size: 2rem
}

select,
input {
  display: inline-block;
  font: inherit;
  line-height: 2rem;
  vertical-align: top;
  margin: 0 10px;
}

select {
  font-size: 1.5rem;
}
// Array of images
const symbols = [
  'https://i.ibb.co/StzKvdm/8.gif',
  'https://i.ibb.co/6Jtv9mK/nec.gif',
  'https://i.ibb.co/6BMt5f9/inv.gif',
  'https://i.ibb.co/FgznhXj/abj.gif',
  'https://i.ibb.co/Jk6X5wk/div.gif',
  'https://i.ibb.co/wwX9xz5/ill.gif',
  'https://i.ibb.co/wKqcxxF/trn.gif',
  'https://i.ibb.co/86gpFf1/cnj.gif',
  'https://i.ibb.co/R6BRtn9/enc.gif'
];

// Reference the first form on page
const form = document.forms[0];
// Collect all inputs, selects, buttons, fieldsets, etc.
const cast = form.elements;
// Reference select
const schools = cast.schools;

// Register select to the change event -- call function changeSymbol()
schools.onchange = changeSymbol;

/** changeSymbol(event)
@Param: event [object]: default Event.Object
As the select changes value so does the src of the element that is in front of it.
//A Pass event object
//B Get event.target (select#schools) value and convert it to a real number
//C Get the element that is in front of select
//D Change that element's src to the url in symbols array at the index of select value
//E* Change the data-idx value to index of select value as well
//F End function
*/
function changeSymbol(event) { //A
  const index = Number(event.target.value); //B
  const images = event.target.nextElementSibling; //C
  images.src = symbols[index]; //D
  images.dataset.idx = index; //E* [OPTIONAL]
  return false; //F
}

// Register form to submit event -- call function magic()
form.onsubmit = magic;

/** magic(event)
@Param: event [object]: default Event.Object
This is left open for whatever purpose when the image is clicked
//A Pass event object
//B Prevent the form from sending data to a server
*/
function magic(event) { //A
  event.preventDefault(); //B
}


7 commentaires

La raison pour laquelle j'ai dit qu'ils ne fonctionneraient pas est à cause des règles de Roll20. Citation des parties pertinentes ci-dessous pour référence. Citant la page de construction de feuilles de Roll20: "Restrictions HTML: Dans le navigateur, la feuille de personnage est essentiellement enveloppée dans une balise géante

. Les attributs d'ID ne peuvent pas être utilisés. (Tout attribut d'ID sur la feuille d'un personnage affecterait la feuille d'un autre personnage dans le même campagne à l'ouverture, aucune fonctionnalité DOM ne peut être utilisée "


Aussi pour ne pas montrer comment j'ai implémenté le code, je n'étais pas tout à fait sûr des directives en termes de quantité de code que je pourrais / devrais partager. Je sentais que j'avais partagé les bits pertinents, car la mise en œuvre complète de la section des sorts répétés et les bits de code JS sont un millier de lignes de code et j'ai trouvé que c'était un peu exagéré, lol. J'apprécie la perspicacité ici, verrai si je peux le faire fonctionner.


Alors, avez-vous lu la réponse complète ? "... essayez de changer tous les identifiants en nom. C'est un avantage de l'élément est le HTMLFormElement API permet une association transparente entre l'identifiant et le nom (ils sont interchangeables dans un formulaire)." ex. en HTML name = '' schools ' au lieu de id = "schools" . BTW j'ai regardé une partie du code dans GH et ils utilisent nom .


La réponse juste mise à jour utilise const form = document.forms [0]; cela fera référence au premier formulaire de la page - id, nom, classe, etc. non nécessaires. Mis à jour le reste, copiez et collez simplement dans la balise de formulaire. Il n'est plus nécessaire de changer quoi que ce soit maintenant que des informations suffisantes ont été fournies.


L'utilisation d'un tableau vous permet également de vous étendre lorsque vous pouvez trouver de bonnes images pour les sous-écoles de magie sauvage et d'élémentaliste (indice utilisez la balise ). J'avais l'habitude de jouer la 1ère et la 2ème éd.


J'apprécie les réponses, merci. Oui, j'ai lu toute la réponse, et comme vous pouvez le voir après avoir vérifié le code sur GH, tout utilise des noms, tout comme la feuille sur laquelle je travaille. Honnêtement, je ne sais pas si, à moins de regarder le code complet, quelqu'un sera capable de traiter les contraintes avec lesquelles je travaille. Je ne peux malheureusement pas copier / coller ce que vous avez ci-dessus, même si je vais essayer de le modifier pour l'adapter à ce qu'il y a d'autre. Souhaitez-moi bonne chance ... Aussi, n'utilisez pas d'écoles de magie standard, c'est pour une conversion 5e Mass Effect, donc en utilisant les types de puissance Mass Effect (Biotic, Tech, Combat).


Cet événement n'est pas standard: "change: spellschool" il doit provenir de l'API mais tout le reste est standard (bien que grossier et inefficace). Remplacez toutes les balises par des div et des étendues qui ne sont pas des contrôles de formulaire. J'ai lu certaines exigences et je me suis arrêté après avoir lu sur les divs et les travées (c'est comme en 1996, je ne pouvais plus supporter)