Я пытаюсь реализовать серверный рендерер для HighCharts. Кажется, все работает нормально, за исключением того, что в результирующей разметке SVG повсюду отсутствуют значения x, y, ширины и высоты. Я считаю, что посредством некоторой отладки я определил проблему в том, что offsetWidth, offsetHeight, offsetTop и offsetLeft не определены для каждого элемента.
Планируется ли включение этих свойств в будущую версию? Кроме того, есть ли обходной путь, который я могу реализовать в настоящее время?
Я думаю, что http://www.w3.org/TR/cssom-view/ необходимо будет реализовать.
мы начали интегрировать cssom, который должен решить некоторые проблемы с SVG.
Было бы действительно здорово, если бы мы могли получить доступ к свойствам offset *, которые понадобились бы для проекта, связанного с холстом.
Как продвигается этот вопрос? Я также был бы признателен за такую функцию для рендеринга бэкэнда с помощью Highcharts.
Я тоже хотел бы это иметь :)
Ребята, у вас есть запасные циклы, чтобы помочь? Лично мне не нужен svg 1.1, но я был бы готов помочь с ним, если вы, ребята, достаточно воодушевлены, чтобы поработать над ним.
@tmpvar : Я бы хотел помочь, но я новичок в этих серверных JS-материалах.
Может быть, вы мне подскажете, с чего начать, и я постараюсь изо всех сил, чтобы что-то заработало :)
Меня тоже очень интересует SVG 1.1, чтобы включить highcharts на сервере. Я хотел бы предложить помощь, но сначала мне нужно познакомиться с SVG 1.0 и его текущей реализацией в jsdom, что может занять некоторое время;)
Я думаю, что первый шаг здесь - взять копию набора тестов (http://www.w3.org/Graphics/SVG/WG/wiki/Test_Suite_Overview) и преобразовать его в безголовый (что может быть довольно сложной задачей)
Затем мы можем добавить level2/svg.js
и приступить к реализации.
В конце концов я, вероятно, дойду до этого, но сейчас это не входит в мой список приоритетов jsdom.
@href реализация svg 1.0 довольно level1/core
но на самом деле не реализует ничего специфичного для svg.
Я думаю, что getBoundingCLientRect не реализован правильно.
У меня есть этот код для вычисления конкретного элемента svg:
var html = '<!DOCTYPE html><html><head><title></title></head><body style="margin: 0; padding: 0;"><svg id="svg" xmlns="http://www.w3.org/2000/svg" version="1.1" style="margin: 0; padding: 0;"><rect style="" x="10" y="10" width="100" height="100" rx="0" ry="0"/></svg></body></html>';
jsdom.env({
html : html,
src: [jquery],
done: function (errors, window) {
var $ = window.$;
var clientBox = $("#svg").find(type)[0].getBoundingClientRect();
console.log(clientBox);
}
});
И вот результат:
{ bottom: 0, height: 0, left: 0, right: 0, top: 0, width: 0 }
Но если я протестирую тот же HTML-код в веб-браузере, результат будет следующим:
{ bottom: 110, height: 100, left: 10, right: 110, top: 10, width: 100 }
@ throrin19 : Прочтите # 653.
Так чего добиться нельзя? Пока мне удалось обойти эту проблему с помощью phantomJS, но он работает очень медленно, и если у меня большой SVG, он вылетает.
Я имею в виду, что это не невозможно, но нам нужно было бы написать целую верстку, и ни у кого не было на это времени.
Я думал об этом, но тут у меня спазмы в мозгу, и мне нужно уйти.
Есть ли тесты помимо кислоты, за которыми можно было бы следить?
+1, обнаружив, что это очень желательная функция
Я использую этот фрагмент для поддержки, и он работает в моем случае. Имейте в виду, что это далеко не правильная реализация. Обратите внимание, что window
должно быть вашим document.parentWindow
.
Если вам нужна лучшая реализация, расширьте код, используя спецификацию:
http://dev.w3.org/csswg/cssom-view/#dom -htmlelement-offsetleft
Object.defineProperties(window.HTMLElement.prototype, {
offsetLeft: {
get: function() { return parseFloat(window.getComputedStyle(this).marginLeft) || 0; }
},
offsetTop: {
get: function() { return parseFloat(window.getComputedStyle(this).marginTop) || 0; }
},
offsetHeight: {
get: function() { return parseFloat(window.getComputedStyle(this).height) || 0; }
},
offsetWidth: {
get: function() { return parseFloat(window.getComputedStyle(this).width) || 0; }
}
});
Кто-нибудь еще добился успеха с тем, что предлагал tobyhinloopen?
@tobyhinloopen :
У меня был другой вариант использования, в котором сработала моя предложенная реализация. Если у вас не работает, продлите. Вероятно, OffsetHeight / width также должны включать отступы. Я бы предложил некоторые хитрые исправления, чтобы заставить его работать, потому что идеальную реализацию сложно реализовать.
Решение, предложенное @tobyhinloopen, кажется прекрасным, но когда я его использую, я получаю «не могу улучшить свойство offsetLeft»
@zallek Думаю, у вас уже есть поддержка offsetLeft :) Что возвращает window.HTMLElement.prototype.offsetLeft
? Если это что-то, кроме undefined, мое решение не сработает
Просто хотел сказать спасибо @tobyhinloopen , ваше решение мне очень пригодилось. :)
@tobyhinloopen Большое спасибо за размещение решения! Это очень полезно и работает до тех пор, пока я использую переменную для установки значения смещения и исключения this
. this
выходит неопределенным, что имеет смысл, учитывая, что контекст не является фактическим классом. Вы этого ожидали?
@jordantomax это привязано к элементу при вызове функции, а не при ее определении. 'this' должен быть элементом, когда вы вызываете его из любого элемента html.
Если это не так, мне хотелось бы увидеть пример.
@tobyhinloopen Спасибо за быстрый ответ. Вот чего я ожидал. Когда я пытаюсь воспроизвести свою проблему в codeandbox, используя реальную среду браузера, она работает правильно. Но при использовании шутки я вижу this
как неопределенное. Я создал небольшой образец репозитория, чтобы показать вам, что я испытываю, возможно, мои настройки неверны.
https://github.com/jordantomax/jest-htmlelement-prototype-sandbox
В связи с этим у меня также возникают проблемы с переопределением таких методов, как scrollIntoView
с использованием jest и jsdom. Есть рекомендуемый способ сделать это?
Большое спасибо за Вашу помощь!
Я думаю, это потому, что вы используете get: () => {}
- синтаксис функции () => {}
вашему this
. Если вместо этого вы используете get() {}
(рекомендуется) или get: function() {}
(альтернативный вариант), это будет работать. @jordantomax
Вы также используете =>
в it
/ describe
своего набора тестов. Я не знаю насчет JEST, но в MOCHA это не рекомендуется, поскольку this
в вашем it
/ test
/ describe
содержит все виды утилиты, к которым вы не можете получить доступ, если используете стрелочные функции. Например, у мокко есть такие вещи, как this.slow()
, this.timeout(4000)
и т. Д.
https://mochajs.org/#arrow -functions
В связи с этим у меня также возникают проблемы с переопределением таких методов, как scrollIntoView, с использованием jest и jsdom. Есть рекомендуемый способ сделать это?
Обычно на MDN есть какие-то полифилы. В противном случае просто попробуйте реализовать его на основе спецификации таким образом, чтобы это соответствовало вашим потребностям. Если все не удается, просто используйте другую среду тестирования. JSDom имеет свое место, но в какой-то момент вы можете захотеть рассмотреть вместо него настоящий браузер. Многие среды тестирования позволяют проводить тестирование в реальных браузерах (даже в нескольких одновременно), а также отправлять отчеты в реальном времени на вашу машину разработки. IIRC Karma делает это -> https://karma-runner.github.io/latest/index.html
У меня было открыто несколько браузеров (firefox chrome safari internet explorer edge + мобильные в симуляторах) одновременно на моей машине, и все они отчитывались в реальном времени с помощью Karma + Mocha.
@tobyhinloopen Правильно ты на всех аккаунтах! Спасибо!! Я все еще не совсем понимаю, зачем нужен getComputedStyle
, и можно ли написать сеттер с учетом этого метода. Для меня это работает:
Object.defineProperties(window.HTMLElement.prototype, {
offsetTop: {
get () {
return this.marginTop
},
set (offset) {
this.marginTop = offset
}
}
})
Еще раз спасибо 🙏
@jordantomax getComputedStyle
извлекает реальный вычисленный стиль для всех свойств CSS, независимо от того, где он был применен (таблица стилей, атрибут style
или из JS). Я не уверен, что this.marginTop
делает то же самое, но я предполагаю, что это так (но, очевидно, только для поля, а не для всех свойств CSS)
@tobyhinloopen А,
Спасибо @tobyhinloopen . Я использую еще более короткую версию. Я думаю, что getComputedStyle
самом деле не нужен, поскольку я лично никогда не добавляю CSS в свои модульные тесты, если он не встроен, поэтому .style
достаточно хорош и быстрее.
Object.defineProperties(window.HTMLElement.prototype, {
offsetLeft: {
get () { return parseFloat(this.style.marginLeft) || 0 }
},
offsetTop: {
get () { return parseFloat(this.style.marginTop) || 0 }
},
offsetHeight: {
get () { return parseFloat(this.style.height) || 0 }
},
offsetWidth: {
get () { return parseFloat(this.style.width) || 0 }
}
})
Было ли это исправлено, я получаю offsetWidth = 0
const dom = new JSDOM(`<!DOCTYPE html><body></body>`);
let document = dom.window.document
let span = document.createElement("span");
span.innerHtml = 'test
span.style.fontSize = 150 + 'px';
span.style.fontFamily = 'Arial'
document.body.appendChild(span)
console.log(span.offsetWidth) // 0
Было ли это исправлено, я получаю offsetWidth = 0
@petran нереально ожидать, что jsdom вычислит ширину вашего SPAN, так как это требует знания размера вашего шрифта и всех унаследованных свойств CSS. Я не думаю, что это цель JSDOM. Если вы хотите более точную симуляцию браузера, подумайте об использовании реального браузера.
Самый полезный комментарий
Я использую этот фрагмент для поддержки, и он работает в моем случае. Имейте в виду, что это далеко не правильная реализация. Обратите внимание, что
window
должно быть вашимdocument.parentWindow
.Если вам нужна лучшая реализация, расширьте код, используя спецификацию:
http://dev.w3.org/csswg/cssom-view/#dom -htmlelement-offsetleft