Issue arises when there are several inline <script> tags containing parameters which result in filtered JSON output

As a newcomer to JavaScript, I am faced with the challenge of creating a centralized glossary within a confined educational environment (LMS) that lacks a database or any other facilitating elements. My objective is to develop a script hosted on our application server that can be integrated into approximately twelve courses. Additionally, one of the requirements outlined by the learning designer is the ability to have two or more glossaries displayed on the same page. The terms and definitions are stored in a file called glossary.json, structured as follows:

{
    "a": [
        {
            "module": "1.1",
            "term": "A term in module 1.1",
            "definition": "<p>A definition in 1.1</p>"
        }, {
            "module": "1.2",
            "term": "A term in module 1.2",
            "definition": "<p>A definition in 1.2</p>"
        }
    ]
}

The goal is to embed relevant terms for each course section directly using a query parameter like so:

<h2>Module 1.1</h2>
<p>Content related to module 1.1 goes here</p>    
<script src="glossary.js?m=1.1"></script>
    
<h2>Module 1.2</h2>
<p>Content related to module 1.2 goes here</p>  
<script src="glossary.js?m=1.2"></script>

The glossary.js script generates a div element with an id based on the m parameter value, displaying only the pertinent terms:

function ajax_get(url, callback) {
    var xmlhttp = new XMLHttpRequest();
    xmlhttp.onreadystatechange = function() {
    if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
        console.log(xmlhttp.responseText);
        try {
            var data = JSON.parse(xmlhttp.responseText);
            } catch(err) {
                console.log(err.message + " in " + xmlhttp.responseText);
                return;
            }
            callback(data);
        }
    };
    xmlhttp.open("GET", url, true);
    xmlhttp.send();
}

var script = document.currentScript;
var queryString = script.src.replace(/^[^\?]+\??/,'');
var urlParams = new URLSearchParams(queryString);
var module = urlParams.get('m');

var el = document.createElement("div");
el.setAttribute("id", "glossary"+module);
document.body.appendChild(el);
 
ajax_get('glossary.json', function(data) {
    var html = "<dl>";
    for (var i=0; i < data["a"].length; i++) {
        if (data["a"][i]["module"] == module) {
            html += '<dt>' + data["a"][i]["term"] + '</dt>';
            html += '<dd>' + data["a"][i]["definition"] + '</dd>';
        }
    }
    html += "</dl>";
    el.innerHTML = html;
});

In the provided example, although the script is executed twice and creates two div elements, it populates only the last one:

<h2>Module 1.1</h2>
<p>Content related to module 1.1 goes here</p>   
<script src="ajax.js?m=1.1"></script>
<div id="glossary1.1"></div>

<h2>Module 1.2</h2>
<p>Content related to module 1.2 goes here</p>  
<script src="ajax.js?m=1.2"></script>
<div id="glossary1.2">
    <dl>
        <dt>A term in module 1.2</dt>
        <dd><p>A definition in 1.2</p></dd>
    </dl>
</div>

I'm encountering challenges getting this functionality to work as expected. Despite each script executing independently until the JSON content is fetched, both ultimately display the same undesired outcome. Could the issue be something simple? Any insights into what might be causing this behavior would be greatly appreciated.

Answer №1

Ensure you are looping through your script tags correctly to extract the src attribute. One way to do this is by implementing a loop that iterates through each script tag and executes your function based on certain conditions. Here's an example of how you can modify your existing code:

// Identify all script tags with src containing "glossary"
var scripts = document.querySelectorAll("script[src*='glossary']");
for (var i = 0; i < scripts.length; i++) {
    if (scripts[i].src) {
        // Extract parameter from src
        var urlParams = new URLSearchParams(scripts[i].src.replace(/^[^\?]+\??/, ''));
        var module = urlParams.get('m');
        
        // Create a new div element
        var el = document.createElement("div");
        el.setAttribute("id", "glossary" + module);
        
        // Insert the newly created div after the current script tag
        scripts[i].parentNode.insertBefore(el, scripts[i].nextSibling);
        
        // Call a function for further processing
        data_();
    }
}

Demo Code :

// Sample data structure
var data = {
  "a": [{
    "module": "1.1",
    "term": "A term in module 1.1",
    "definition": "<p>A definition in 1.1</p>"
  }, {
    "module": "1.2",
    "term": "A term in module 1.2",
    "definition": "<p>A definition in 1.2</p>"
  }]
}

// Select script tags with src containing "glossary"
var scripts = document.querySelectorAll("script[src*='glossary']");
// Iterate through the selected script tags
for (var i = 0; i < scripts.length; i++) {
    if (scripts[i].src) {
        // Extract parameters from the src
        var urlParams = new URLSearchParams(scripts[i].src.replace(/^[^\?]+\??/, ''));
        var module = urlParams.get('m');
        
        var el = document.createElement("div");
        el.setAttribute("id", "glossary" + module);
        
        scripts[i].parentNode.insertBefore(el, scripts[i].nextSibling);
        data_(); // Invoke the function
    }
}

function data_() {
    var html = "<dl>";
    for (var i = 0; i < data["a"].length; i++) {
        if (data["a"][i]["module"] == module) {
            html += '<dt>' + data["a"][i]["term"] + '</dt>';
            html += '<dd>' + data["a"][i]["definition"] + '</dd>';
        }
    }
    html += "</dl>";
    el.innerHTML = html;
}
<h2>Module 1.1</h2>
<p>Course content about module 1.1 goes here</p>
<script src="glossary.js?m=1.1"></script>

<h2>Module 1.2</h2>
<p>Course content about module 1.2 goes here</p>
<script src="glossary.js?m=1.2"></script>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The process of incorporating user properties into the output of a Service Bus topic from a Javascript Azure Function

I'm currently developing a TypeScript Azure Function that utilizes an Azure Service Bus topic as its output. Although I am able to send messages successfully, I have encountered difficulties in setting custom metadata properties for the message. In m ...

Is there a way to create a diagonal movement for an image by clicking on another HTML element?

<!DOCTYPE html> <html> <head> <meta charset="UTF-9"> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> <script> $(function() { $(document).re ...

Steps for sending a POST request for every file in the given array

I am working on an angular component that contains an array of drag'n'dropped files. My goal is to make a POST request to http://some.url for each file in the array. Here is what I have been attempting: drop.component.ts public drop(event) { ...

The HTML function transforms blank spaces into the symbol "+"

Just starting out with a question: I created a basic submission form, but I noticed that if there are any spaces in the inputs, the values get changed to a plus sign (+). Here's my form: <form name="input" action="search" method="get"> Web Ad ...

Getting a variable from an ajax call and using it in a Pug template

Currently, I am experimenting with Express and Pug to learn some new concepts. Upon making a request to a website, I received some dynamic information stored in an array. However, I am facing challenges when trying to iterate over this array using Pug. The ...

Ways to disable an AJAX loading animation

In my current script, I am loading external content using the following code: <script type="text/javascript"> var http_request = false; function makePOSTRequest(url, parameters) { // Code for making POST request } function alertContents() { ...

Issue with ESlint global installation in macOS root terminal

Having trouble installing ESlint globally on my Mac running Mojave 10.14.6. Every time I try to run 'npm install -g eslint' I keep encountering this error: Your operating system has rejected the operation. npm ERR! It seems that you lack the nec ...

Error: Unable to execute $(...).stellar since it is not a recognized function

Having some trouble implementing the stellar plugin. I've included all the necessary js, but keep getting an error in the dev tools console: 'Uncaught TypeError: $(...).stellar is not a function'. Here's what I have in the head tags: ...

Adding dynamic elements to a pop-up window with the use of jQuery's .load() function

When implementing Javascript to create a modal, I have encountered an issue where the close button disappears. The modal opens and loads different HTML files dynamically using the jQuery load() method, but the close button vanishes. I suspect that the mod ...

An error of undefined Angular Service/Factory has occurred

I created a factory service called siteCollection: spApp.factory('siteCollection', function(){ return { usersObject : [], getUsers : function (){ $().SPServices({ operation: "GetUserCollectionFromSite", completef ...

Extract specific information from Ansible Output

Looking to extract hostnames from the output obtained after running a specific playbook. The relevant output is shown below. ok: [localhost] => msg: changed: false clusters: RDG1-DC-2: datacenter: RDG1 drs_default_vm_beha ...

Error message: The module '@project-serum/anchor' does not export the object 'AnchorProvider' as intended

I encountered an issue while attempting to run my react application. The issue: Attempted import error: 'AnchorProvider' is not exported from '@project-serum/anchor'. The import declaration in my code: import idl from './idl.json ...

Creating fixed-size arrays within a Mongoose schema is a commonly sought after feature that allows

For a specific scenario where I have example input: [[1,2],[3,2],[1,3],...,[4,5]] I am wondering about the correct way to define a model schema in mongoose. Here is my initial Schema: const SubproductSchema = new Schema({ ... positions: [{ type: ...

Tips for maintaining a scrollable Material-UI Table with dynamic height?

I'm encountering an issue with the Material-UI Table component in terms of its size and scrollability. Summary: The Material-UI table only becomes scrollable when its parent has a fixed size. If I set the size to 100% to fit the parent, it overflows. ...

Verifying if checkboxes are selected in PHP using JavaScript

echo '<div class="col-lg-10 col-lg-offset-1 panel">' . "<table id='data' class='table'> <tr> <th></th> <th>Document No</th> <th>AWB NO</th> ...

Steps for including a path to a base64 encoded image

I am currently facing a challenge in embedding images into my emails where I need to encode them using an online tool. The issue I am encountering is that the email template I am using has a dynamic URL, with ${loginurl}/images as the path to my image. H ...

Transforming JSON data into a visually appealing pie chart using highcharts

I'm having trouble loading my JSON string output into a highcharts pie chart category. The chart is not displaying properly. Here is the JSON string I am working with: var json = {"{\"name\":\"BillToMobile\"}":{"y":2.35},"{\ ...

Merging multiple references within properties in JSON Schema to set "AdditionalProperties = false"

I need to categorize the properties based on their types, like so: { "type": "object", "additionalProperties": false, "properties": { "allOf": [ { "$ref": "type/blue.json#/defi ...

"Encountering a Webpack issue while attempting to submit an AJAX form

Today, I encountered an issue while trying to submit a contact form using AJAX. This is not my first time working with AJAX, but it's my first time incorporating webpack into the process. Here's a snippet from my index.js file: $document.on(&ap ...

Fatal error: The street number index is not defined

I am facing an issue with displaying decoded JSON data in my view. When I try to access the streetNumber index, I receive the following error: ErrorException (E_ERROR) Undefined index: streetNumber Below is a snippet of the data: array(11) { [0] ...