Проблема с несколькими рядный ‘s with parameters that output filtered json

#javascript #json #ajax

#javascript #json #ajax

Вопрос:

Я довольно новичок в js и пытаюсь создать централизованный глоссарий в ограниченной образовательной среде (LMS) без базы данных или чего-либо, что сделало бы это проще. Мне нужно создать скрипт, размещенный на нашем сервере приложений, который может быть встроен в дюжину или около того курсов, и требование дизайнера обучения заключается в том, что на одной странице может быть два или более. Термины и определения находятся в glossary.json и выглядят примерно так:

 {
    "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>"
        }
    ]
}
  

То, что я пытаюсь сделать, это встроить соответствующие термины для раздела курса встроенным с параметром запроса следующим образом:

 <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>
  

glossary.js создает div с идентификатором, названным в честь параметра m, и должен выводить только соответствующие термины, например:

 function ajax_get(url, callback) {
    var xmlhttp = new XMLHttpRequest();
    xmlhttp.onreadystatechange = function() {
    if (xmlhttp.readyState == 4 amp;amp; 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;
});
  

Однако в приведенном выше примере, даже если скрипт «вызывается» дважды и создаст два div, он будет заполнять только последний, например:

 <h2>Module 1.1</h2>
<p>Course content about 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>Course content about 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>
  

Я просто не могу заставить его работать. Почему каждый скрипт счастлив быть автономным до тех пор, пока не будет вызван JSON. Я пробовал два разных способа получения содержимого JSON, но выдал тот же нежелательный результат. У меня такое чувство, что это может быть что-то простое, но любые советы о том, что вызывает это, были бы весьма признательны.

Комментарии:

1. Привет, вы вызываете этот скрипт по щелчку чего-либо? Пожалуйста, уточните подробнее

2. эй, события щелчка нет, предполагается, что скрипт просто загружает термины глоссария при просмотре страницы

3. Но у вас нет никакого цикла для итерации по scripts тегу и получения параметра только из этого скрипта? Приведенный выше js-код вызовет вашу функцию только 1 раз ..? Как вы перебираете все скрипты?

4. А, я понимаю, о чем ты говоришь. Я надеялся, что если скрипт будет встроен в HTML на странице дважды, он будет выполняться дважды.

Ответ №1:

Вы не перебираете свои script теги оттуда, откуда вам нужно получить src , поэтому для преодоления этого один из способов — использовать некоторые loop , которые будут перебирать script тег и в зависимости от этого выполнять вашу функцию.Изменения, которые вы можете внести в свой текущий код :

    //get all script tag with src="glossary"
    var scripts = document.querySelectorAll("script[src*='glossary']");
    for (var i = 0; i < scripts.length; i  ) {
     if (scripts[i].src) 
    //get parameter
    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_();//call some function to do further process
    }
  

Демонстрационный код :

 //your data
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>"
  }]
}

//get script tag with src="glossary"
var scripts = document.querySelectorAll("script[src*='glossary']");
//loop through it
for (var i = 0; i < scripts.length; i  ) {
  if (scripts[i].src)
  //get param
    var urlParams = new URLSearchParams(scripts[i].src.replace(/^[^?] ??/, ''));
  var module = urlParams.get('m');
  var el = document.createElement("div");
  el.setAttribute("id", "glossary"   module);
  //insert newly created div after script tag
  scripts[i].parentNode.insertBefore(el, scripts[i].nextSibling);
  data_();//call your 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>  

Комментарии:

1. спасибо, что дали ему ход, но по какой-то причине я получаю разные результаты для фрагмента кода. точная копия / вставка вашего примера выводит два <div id=»glossary1.1″> и когда я заменяю данные глоссария на файл JSON, я возвращаюсь к исходной проблеме, заключающейся в том, что он заполняет только второй <div>

2. можете ли вы создать jsfiddle своего кода? Кроме того, вам не нужно вызывать ajax несколько раз, просто вызывайте только один раз и используйте возвращаемые данные для заполнения ваших divs.