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