Skip to content

Change icon if text contains string with jQuery

I have the following structure that cannot be changed:

<div class="activityinstance">
        <a class="aalink" onclick="" href="https://...">
           <img src="..../icon" class="iconlarge activityicon">
           <span class="instancename">[h5p-iv] Interaktives Video
                 <span class="accesshide ">Interactive Content</span>
           </span>
        </a>
</div>

What I need to do, is to change the icon if span.instancename contains “[h5p-iv]” (plus, ideally, delete or hide that partial string from the span)

The “if” and “then” are not part of the code and the last line is unfinished, this is intended to show what I want to achieve. How do I construct an if-then in Javascript to achieve that logic?

if

$(".activityinstance .instancename:contains('[h5p-iv]')")

then

 $(".activityicon")  attr("src", "/static/img/icons/video.svg");

The second part is to change

<span class="instancename">[h5p-iv] Interaktives Video</span>

into

<span class="instancename">Interaktives Video</span>

that is: removing the string from “contains”


Explanation: Moodle does not discern H5P activities, they all get the same icon. Teachers are supposed to be able to enter strings to the activity-names in order to get a different icon. So in the end there will be a list of strings linked to different icons. If that can be simplified by a switch etc., even better, but there are not that many different icons, that it would be unreasonable to repeat the code regardingly.


Additions 1: added span.accesshide because it became visible after string replacement.


Additions 2: I actually have a (kind of) working code now, but I suppose it could be done more safely and elegantly…. Any suggestions?

var elem = $(".instancename:contains('[icon-video]')");
if (elem.length) {
   $(".instancename:contains('[icon-video]')").each(function() {
      $(this).prev().attr("src", "/static/img/icons/video.svg");
      $(".accesshide").remove();
      elem.text(function(_, text) { return text.replace('[icon-video] ', '');  
      });
   });
}

Esp. removing the .accesshide worries me, I am not sure, what it does and I would rather just remove the display and not the whole thing from the DOM. I suppose the text replace reads the whole text including the contained span.accesshide and puts the text back minus the replaced text – but also removing the span.accesshide-tag thus it looses its css that makes it invisible.

Answer

jQuery object is truthy so you would need to check its length to see if it found the element. Other thing you need to do is just do a simple string replacement

var elem = $(".activityinstance .instancename:contains('[h5p-iv]')");
if (elem.length) {
  $(".activityicon").attr("src", "/static/img/icons/video.svg");
  elem.text(function(_, text) { return text.replace('[h5p-iv] ', ''); });
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="activityinstance">
  <a class="aalink" onclick="" href="https://...">
    <img src="..../icon" class="iconlarge activityicon">
    <span class="instancename">[h5p-iv] Interaktives Video</span>
  </a>
</div>

Now since you said it could be multiple

function replaceThis(text, imgPath) {
  $(".activityinstance .instancename:contains('" + text + "')").each(function() {
    const instanceName = $(this);
    instanceName.find(".accesshide").hide();
    instanceName.prev("img").attr("src", imgPath);
    instanceName.contents().each(function(_, node) {
      if (node.nodeValue && node.nodeValue.includes(text)) {
        node.nodeValue = node.nodeValue.replace(text, "");
      }
    })
  });
}

replaceThis("[h5p-iv] ", "http://placekitten.com/20/20");
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="activityinstance">
  <a class="aalink" onclick="" href="https://...">
    <img src="..../icon" class="iconlarge activityicon">
    <span class="instancename">[h5p-iv] Interaktives Video
                 <span class="accesshide ">Interactive Content</span>
    </span>
  </a>
</div>