Как получить доступ к CSS-контенту с помощью JavaScript
Я генерирую нумерацию своих заголовков и цифр с помощью свойств CSS counter
и content
:
img.figure:after {
counter-increment: figure;
content: "Fig. " counter(section) "." counter(figure);
}
Это (соответствующий браузер) дает хорошую маркировку "Рисунок 1.1", "Рисунок 1.2" и т.д. после любого изображения.
Вопрос: Как я могу получить доступ к этому из Javascript? Вопрос двояк в том, что я хотел бы получить доступ либо к текущему значению определенного счетчика (при определенном DOM node), либо о значении CSS-контента (в некотором DOM node) или, обе информации.
Фон: я хотел бы добавить к ссылкам обратную ссылку на цифры соответствующего номера, например:
<a href="#fig1">see here</h>
------------------------^ " (Fig 1.1)" inserted via JS
Насколько я вижу, это сводится к этой проблеме:
Я мог получить доступ к content
или counter-increment
через getComputedStyle
:
var fig_content = window.getComputedStyle(
document.getElementById('fig-a'),
':after').content;
Однако это не живое значение, а одно, указанное в таблице стилей. Я не могу найти какой-либо интерфейс для доступа к реальному живому значению. В случае счетчика нет даже реального свойства CSS для запроса.
Изменить: Копаем все глубже и глубже по спецификациям DOM, я нашел интерфейс счетчика стиля DOM уровня 2. Это, по-видимому, a) позволяет получить доступ к текущему значению счетчика и b) быть реализовано в Firefox, по крайней мере. Однако я понятия не имею, как его использовать. Мой текущий подход умер трагически после выхода Firebug:
// should return a DOM 2 Counter interface implementation...
window.getComputedStyle(fig_a_element, ':after')
.getPropertyCSSValue("counter-increment")[0]
.getCounterValue();
[Exception... "Modifications are not allowed for this document" code: "7"
nsresult: "0x80530007 (NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR)"
location: "http://localhost/countertest.html Line: 71"]
Любая идея, как это можно воплотить в жизнь, будет высоко оценена.
Изменить 2: По-видимому, я неверно истолковал объект Counter объекта DOM Level 2 Style. Он также не имеет свойства для возврата текущего значения счетчика. Это делает вышеуказанный подход недействительным.
Новый подход: есть ли возможность прочитать содержимое псевдоэлемента через DOM? То есть, могу ли я выбрать псевдоэлемент (treeWalker
приходит на ум), а затем получить его nodeValue
? (Если вы начнете вводить "jQuery" сейчас, передумайте, чтобы изменить этот термин на "Sizzle"...)
Ответы
Ответ 1
Я не могу найти никакого интерфейса для доступа к реальному живому значению. [счетчика]
Да. Я не думаю, что он есть. К сожалению.
Единственное, о чем я могу думать, - это пройти через каждый элемент (включая его псевдоэлементы :before
/:after
) перед элементом в документе, искать счетчики и суммировать количество их.
Очевидно, что это ужасно. Если вы попытаетесь воспроизвести собственный механизм браузера counter
, он, вероятно, будет проще (и гораздо более совместим с учетом отсутствия поддержки счетчика/контента IE <= 7), чтобы просто заменить его на свой собственный script - основанные счетчики. например. что-то вроде:
<a href="#prettypicture">this</a>
<div class="counter level=0">...</div>
<img id="prettypicture" class="counter level=1" alt="ooo, pretty"/>
window.onload= function() {
var counters= Node_getElementsByClassName(document.body, 'counter');
var indices= [];
for (var counteri= 0; counteri<counters.length; counteri++) {
var counter= counters[counteri];
var level= Element_getClassArgument(counter, 'level');
while (indices.length<=level)
indices.push(0);
indices[level]++;
indices= indices.slice(level+1);
var text= document.createTextNode('Figure '+indices.join('.'));
counter.parentNode.insertBefore(text, counter.nextSibling);
if (counter.id!=='') {
for (var linki= document.links.length; linki-->0;) {
var link= document.links[i];
if (
link.hostname===location.hostname && link.pathname===location.pathname &&
link.search===location.search && link.hash==='#'+counter.id
) {
var text= document.createTextNode('('+indices.join('.')+')');
link.parentNode.insertBefore(text, link.nextSibling);
}
}
}
}
};
Ответ 2
читайте это:
Сгенерированный контент не изменяет дерево документов. В частности, это не возвращаются на язык документа процессор (например, для повторной обработки).
Содержимое, указанное в таблице стилей, не становится частью DOM.
поэтому по этой причине getComputedStyle не будет работать в этом случае; я думаю, что единственный способ - выполнить классический цикл через, как описано ниже!
Ответ 3
Я не могу найти какой-либо интерфейс для доступа к реальному живому значению.
Если вы не можете получить значение из window.getComputedStyle
, кажется, что это было бы невозможно.
Что еще более важно, хотя он может это сделать, я думаю, что это может привести к злоупотреблению CSS, поскольку на данный момент вы нарушаете барьер между контентом и презентацией.
Проверьте этот связанный вопрос Что такое использование свойства css "Content" ?
Ответ 4
Я бы поместил ваш css в Javascript, это позволит вам получить заголовок рисунка, а также увеличить охват браузера. Используя jQuery, вы сделали бы что-то вроде этого:
$(function() {
var section = 0;
$(".section").each(function() {
section++;
var figure = 0;
$(this).find("img.figure").each(function() {
figure++;
var s = "Fig. " + section + "." + figure;
$(this).attr({alt:s}).after(s);
});
});
});
Тогда вы могли бы сделать:
<div class="section">blabla <img id="foo" src="http://www.example.com/foo.jpg"></div>
<p>Lorem ipsum dolor sit amet <a href="#foo" class="figurereference">see here</a></p>
<script type="text/javascript">
$(function() {
$("a.figurereference").each(function() {
var selector = $(this).attr("href");
var $img = $(selector);
var s = $(this).text() + " (" + $img.attr("alt") + ")";
$(this).text(s);
});
});
</script>
Хотя я согласен, что делать это с помощью CSS было бы очень аккуратно.
Ответ 5
Я не уверен, как это реализовано, но jquery.css() селектор работает для этого в последней версии сафари, chrome и firefox.
.foo { content: 'hello'; }
...
var value = $('.foo').css('content').toString();
Здесь ручка этого живого действия, чтобы вводить иконки SVG непосредственно из css; http://codepen.io/shadowmint/pen/unvLB
(обратите внимание, что значение содержимого должно быть экранировано, то есть "1", с использованием содержимого: 1 не будет работать)