#javascript #content-security-policy #geonames
#javascript #content-security-policy #геонимы
Вопрос:
Я пытался весь день и везде искал решение. Это не было действительно успешным, и, честно говоря, после нескольких лет просмотра stackoverflow я впервые отправляю сообщение в поисках помощи. 🙂
Недавно я внедрил строгий CSP. Я раздвоил класс JSONscriptRequest Джейсона Левитта, чтобы больше защитить динамический тег (http://www.geonames.org/export/jsr_class.js ) с одноразовым номером. Я ценю это, потому что я действительно настраивал и часто использовал его (от него зависит множество модулей).
Первоначально скрипт выводил это в HTML :
<div class="suggestions" id="pcId0" onmousedown="suggestBoxMouseDown(0)" onmouseover="suggestBoxMouseOver(0)" onmouseout="suggestBoxMouseOut(0)">...</div>
<div class="suggestions" id="pcId1" onmousedown="suggestBoxMouseDown(1)" onmouseover="suggestBoxMouseOver(1)" onmouseout="suggestBoxMouseOut(1)">...</div>(and so on, depending on the number of results.)
...
Все они имеют один и тот же класс (предложения). Я знаю, что могу сделать это, чтобы заменить встроенные обработчики событий, но без каких-либо параметров :
document.getElementById("placeInput").addEventListener("input", postalCodeLookup)
Я попытался сделать это
document.getElementById("placeInput").addEventListener("change", function() {
var suggestions = document.getElementsByClassName('suggestions');
console.log(suggestions);
for (i = 0; i < suggestions.length; i ) {
suggestions[i].addEventListener("mousedown", suggestBoxMouseDown([i]));
suggestions[i].addEventListener("mouseover", suggestBoxMouseOver([i]));
suggestions[i].addEventListener("mouseout", suggestBoxMouseOut([i]));
}
});`
И снова это был полный сбой.
Я не знаю, как передать переменную в мои функции так же легко, как мы могли раньше.
Соответствующие функции :
// remove highlight on mouse out event
function suggestBoxMouseOut(obj) {
document.getElementById('pcId' obj).className = 'suggestions';
}
// the user has selected a place name from the suggest box
function suggestBoxMouseDown(obj) {
closeSuggestBox();
var postalcodeInput = document.getElementById("postalcodeInput");
var placeInput = document.getElementById("placeInput");
var latitude = document.getElementById("latitude");
var longitude = document.getElementById("longitude");
postalcodeInput.value = postalCodes[obj].postalCode;
placeInput.value = postalCodes[obj].placeName " (" postalCodes[obj].postalCode ", " postalCodes[obj].countryCode ")";
latitude.value = postalCodes[obj].lat;
longitude.value = postalCodes[obj].lng;
}
// function to highlight places on mouse over event
function suggestBoxMouseOver(obj) {
document.getElementById('pcId' obj).className = 'suggestionMouseOver';
}
У кого-нибудь есть идея?
Ответ №1:
Итак, быстрые идеи по рефакторингу кода:
- Реализовать правила для классов
.suggestions
иsuggestionMouseOver
с.sugestions
помощью и:hover
селектора псевдоклассов в CSS:.suggestions { ... rules for mouse not over ... } .suggestions:hover { ... rule changes for when when hovering over *.suggestions ... }
Это должно устранить необходимость мониторинга
mouseenter
иmouseleave
событий для.suggestion
элементов класса просто для изменения стиля. (Обратитеmouseover
внимание, иmouseout
может срабатывать при наведении курсора мыши на дочерние элементы класса hover.) - Создайте
data-
атрибут для элементов HTML для записи номера индекса предложения. В настоящее время это реализовано как числовой суффикс значенияid
атрибута, который, оставаясь возможным, не является самым чистым решением:<div class="suggestions" data-num="0">...</div> <div class="suggestions" data-num="1">...</div> <!-- and so on -->
- Хотя обработка событий может быть делегирована путем предоставления одного события для общего родительского элемента и просмотра
target
атрибута запущенных событий, прямой подход все равно может заключаться в том, чтобы оставаться с прослушивателем событий для каждогоdiv
элемента:function sugestionMouseDown( event) { let suggestionDiv = event.currentTarget; let suggestionNumber = suggestionDiv.dataset.num; // process parameters suggestionDiv and suggestionNumber // ... } Array.from( document.getElementsByClassName('suggestions') ) .forEach( div => div.addEventListener("mousedown", suggestionMouseDown));
Комментарии:
1. Большое спасибо @traktor53. Следуя вашим советам, все работает нормально!
Ответ №2:
Благодаря хорошим советам @traktor53, это то, что я придумал.
Примечание для будущих исследователей stackoverflow: цель состоит в том, чтобы заменить встроенные обработчики событий javascript, содержащие аргумент (например: onmouseout(0)
, …). Причина заключается в соблюдении политики безопасности контента (CSP), которая по понятным причинам не разрешает встроенный скрипт. Я применяю приведенный ниже код к пользовательскому jsr_class.js получение результатов по API GeoNames.
HTML
Он динамически генерируется следующим образом :
<div class="suggestions" id="pcId0" data-num="0"> Vannes - (56000) amp;nbsp;FR</div>
<div class="suggestions" id="pcId1" data-num="1"> Vannes - (56001 CEDEX) amp;nbsp;FR</div>
<div class="suggestions" id="pcId2" data-num="2"> Vannes - (56002 CEDEX) amp;nbsp;FR</div>
<div class="suggestions" id="pcId3" data-num="3"> Vannes - (56003 CEDEX) amp;nbsp;FR</div>
CSS
Цель здесь — заменить старые функции onmouseover и onmouseout
.suggestions {
font-size: 14;
background-color: #fff;
border-radius: 5px;
}
.suggestions:hover {
font-size: 14;
background: #456ae7;
color: white;
cursor: pointer;
border-radius: 5px;
}
Javascript
Я не хотел изменять свою исходную функцию по практическим соображениям, я знаю, что можно использовать более чистые методы.
function triggerMouseDown( event) {
let suggestionDiv = event.currentTarget;
let suggestionNumber = suggestionDiv.dataset.num;
suggestBoxMouseDown(suggestionNumber);
}
document.getElementById("placeInput").addEventListener("change", function() {
Array.from( document.getElementsByClassName('suggestions') )
.forEach( div => div.addEventListener("click", triggerMouseDown));
});