Я окрашиваю текстовые сообщения каждого пользователя в свое приложение в зависимости от цвета, который они выбирают. Для этого я динамически добавляю правила в таблицу стилей по мере того, как новые пользователи выбирают свой цвет.
Проблема, которую я пытаюсь решить, - обновить этот цвет с помощью AJAX без перезагрузки страницы.
Я применяю цвет, назначая класс, который соответствует каждому пользователю и истории, которую он отправляет:
<span class="<%= "contrib-u#{snippet.user.id}-s#{@story.id}" %>">
(code to display text submission)
</span>
Я создаю классы для каждого пользователя, которые соответствуют этому формату contrib-u1-s2
(вклад для пользователя 1, история 2), используя JQuery один раз при загрузке приложения:
$(document).one 'turbolinks:load', ->
build_contribution_styles()
build_contribution_styles = ->
req = $.get('/contributions/index')
req.done (data) ->
user_sheet = document.styleSheets[5]
for contribution in data
user_sheet.addRule(
".contrib-u" + contribution['user_id'] + "-s" + contribution['story_id'],
"color: #" + contribution['color']
)
Пока это прекрасно работает. Представление каждого пользователя для каждой истории правильно окрашено на основе этих динамически созданных классов.
Далее я предоставляю пользователю текстовое поле, чтобы он мог выбрать новый цвет для своих представлений:
<%= text_field_tag :snippet_color,
current_user.get_contribution_color(@story),
class: "jscolor centered-text",
data: {user_id: current_user.id, story_id: @story.id}
%>
Затем в JQuery я присоединяю прослушиватель событий к этому текстовому полю, чтобы обновить базу данных и классы вновь выбранным цветом:
$(document).on 'turbolinks:load', ->
$('#snippet_color').change (e) -> handle_snippet_color_change(e, @)
handle_snippet_color_change = (e, input) ->
data = {
contribution: {
story_id: $(input).data('story-id'),
user_id: $(input).data('user-id'),
color: $(input).val()
}
}
req = $.post('/contributions/update', data)
req.done (data) ->
els = $('.contrib-u' + data['user_id'] + '-s' + data['story_id'])
els.css('color', data['color'])
Это тоже хорошо работает, но только после перезагрузки страницы. Обновления класса не применяются к элементам до тех пор.
Это несколько смущает меня, потому что есть ряд других случаев, когда я динамически изменяю стиль CSS элемента с помощью javascript, и он изменяется без обновления страницы. Например, много раз в этом приложении я выбираю элемент и переключаю его свойство display, чтобы скрыть или показать его.
Я нашел несколько источников информации о «перезагрузке стиля CSS без обновления страницы», но ни один из них, похоже, не решает эту конкретную проблему. Одно из предложений заключалось в том, чтобы поместить эти новые правила CSS в тег стиля на странице с этими элементами, чтобы они автоматически обновлялись без перезагрузки, но в моем случае это не имеет значения.
РЕДАКТИРОВАТЬ: рабочий раствор
Теперь он работает, удалив предыдущее правило и добавив обновленное правило в таблицу стилей:
req = $.post('/contributions/update', data)
req.done (data) ->
selector = '.contrib-u' + data['user_id'] + '-s' + data['story_id']
sheet = document.styleSheets[5]
rules = sheet.cssRules
for i in [0...rules.length]
if rules[i].selectorText is selector
sheet.deleteRule(i)
sheet.addRule(selector, "color: #" + data['color'])
Проблема заключалась в том, что я просто обновлял стили для существующих элементов. Я все еще не уверен, почему их обновленные стили не были применены немедленно, но этот новый подход достигает желаемой функциональности.