通过 apache 服务器内部的服务器端过滤,在 SVG 中动态包含 JavaScript
Dynamic inclusion of javascript in SVG by means of server side filtering inside apache server
几年前,我编写了一些代码来自动将一些javascript代码包含在http服务器提供的html页面中。该方法记录在博客条目和此 StackOverflow 问题中。在过去的几年里,这个解决方案对我很有帮助。
两句话的方法:
- 对于 HTTP 服务器提供的每个完整 HTML 页面,通过服务器端替换将一些占位符添加到页面底部
- 该占位符再次替换为要通过服务器端包含的 JavaScript 代码
现在,我想扩展该解决方案,并将相同的逻辑应用于基于 SVG 而不是 HTML 作为文档格式的页面。注意:不是 html 页面中包含的 SVG,而是通过链接直接引用的 SVG 格式的页面。
扩展本身不是问题,javascript代码包含在SVG标记中。问题是代码未执行。不幸的是,我对 SVG 中的脚本知之甚少,这就是为什么我有些迷茫的原因。也许有人可以给我一个提示,这里出了什么问题:-)
各种 apache vhosts 定义中包含的过滤器链:
# ----------
# internal requests to include the piwik tracking code at the bottom of every html page
FilterDeclare PIWIK_token
FilterProvider PIWIK_token SUBSTITUTE resp=Content-Type $text/html
SUBSTITUTE 's|^'s*</body>|<!--#include virtual="/piwik"--></body>|iq'
FilterProvider PIWIK_token SUBSTITUTE resp=Content-Type $image/svg+xml
SUBSTITUTE 's|^'s*</svg>|<!--#include virtual="/piwik"--></svg>|iq'
FilterDeclare PIWIK_code
FilterProvider PIWIK_code INCLUDES resp=Content-Type $text/html
FilterProvider PIWIK_code INCLUDES resp=Content-Type $image/svg+xml
FilterChain PIWIK_token PIWIK_code
# map virtual request to the file system
Alias /piwik /srv/www/internal/piwik.php
# all that is left for the virtual host is to do two things:
# SetEnv PIWIK_ID 15
# Include /etc/apache2/vhosts.d/_internal.inc
# note: the '15' above is an example piwik site id
要包含的 javascript 代码是 piwik 跟踪代码段的略微修改版本:
<?php
define('piwikBase','https://some.domain.xxx/stats/');
define('piwikSite',apache_getenv('PIWIK_ID'));
if(is_numeric(piwikSite)){
?>
<script type="text/javascript">
var _paq = _paq || [];
_paq.push(["trackPageView"]);
_paq.push(["enableLinkTracking"]);
(function() {
var u="<?= piwikBase ?>";
_paq.push(["setTrackerUrl", u+"piwik.php"]);
_paq.push(["setSiteId", "<?= piwikSite ?>"]);
var d=document, g=d.createElement("script"), s=d.getElementsByTagName("script")[0]; g.type="text/javascript";
g.defer=true; g.async=true; g.src=u+"piwik.js"; s.parentNode.insertBefore(g,s);
})();
</script>
<?php } else { ?>
<!-- invalid piwik site id: <?php echo piwikSite;?> -->
<?php } ?>
如前所述:扩展有效,javascript代码成功包含在SVG文档中。但是它显然没有被激活,我没有看到原因......
交付的最终 SVG 如下所示:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
version="1.2"
width="100%"
height="100%"
viewBox="0 0 640 400"
docname="somedocument.svg">
[... content of the SVG ...]
<script type="text/javascript">
var _paq = _paq || [];
_paq.push(["trackPageView"]);
_paq.push(["enableLinkTracking"]);
(function() {
var u="https://some.domain.xxx/stats/";
_paq.push(["setTrackerUrl", u+"piwik.php"]);
_paq.push(["setSiteId", "15"]);
var d=document, g=d.createElement("script"), s=d.getElementsByTagName("script")[0]; g.type="text/javascript";
g.defer=true; g.async=true; g.src=u+"piwik.js"; s.parentNode.insertBefore(g,s);
})();
</script>
</svg>
只是猜测,但我会尝试更改代码,以便将动态脚本注入替换为带有 xlink:href
的内联脚本标签(我已经测试过动态执行此操作,就像您的代码使用看似"更正确"createAttibuteNS('xlink','href','...')
但结果也没有执行)
生成的代码如下所示(尚未在真实环境中测试,因此拼写错误):
<?php
define('piwikBase','https://some.domain.xxx/stats/');
define('piwikSite',apache_getenv('PIWIK_ID'));
if(is_numeric(piwikSite)){
?>
<script type="text/javascript"><![CDATA[
var _paq = _paq || [];
_paq.push(["trackPageView"]);
_paq.push(["enableLinkTracking"]);
_paq.push(["setTrackerUrl", "<?= piwikBase ?>piwik.php"]);
_paq.push(["setSiteId", "<?= piwikSite ?>"]);
]]></script>
<script type="text/javascript"
xmlns:xlink="http://www.w3.org/1999/xlink"
xlink:href="<?= piwikBase ?>piwik.js"
defer="defer" async="async"></script>
<?php } else { ?>
<!-- invalid piwik site id: <?php echo piwikSite;?> -->
<?php } ?>
我不确定那些defer
和async
的东西,它是否在 SVG 中有任何影响。我已经用简单的datauri示例对此进行了测试,它似乎运行良好。
笔记:
- 脚本或其某些父级
xmlns:xlink="http://www.w3.org/1999/xlink"
是必要的,但很可能您的 SVG 已经拥有它 - 在这种情况下,
CDATA
不是必需的,但是如果您打算将来使用<
或&
...你知道吗。
不能使用 创建 SVG 脚本元素
g=d.createElement("script")
你需要写
g=d.createElementNS("http://www.w3.org/2000/svg", "script")
- 如何使用javascript从主svg对象动态创建svg视图框
- JavaScript-动态SVG-onload属性-未触发事件
- 如何自动保存动态生成的HTML SVG元素
- 将形状/掩码动态添加到内联svg中
- 动态创建foreignGroup并将其添加到svg中有什么问题
- 将 src 内容动态加载到 SVG 图像
- SVG元素的动态动画在IE中不起作用
- 在HTML中使用javascript动态创建SVG元素
- 如何在svg高度动态变化时使用viewbox
- 动态注入SVG过滤器并应用于HTML
- 使用d3.js在绑定数据内数组(以恒定性动态生成d3.svg.line)
- 动态文本的 SVG 线条动画
- Snap.svg可以't使用jQuery动态地(并且成功地)找到附加的SVG元素
- 在聚合物中动态生成 SVG 的样式
- JavaScript动态地制作SVG是行不通的,为什么
- 使用 Javascript 对 SVG 进行动态修改不起作用
- 动态更改 SVG 元素
- 使用 js 动态添加 SVG 掩码
- svg 动画从动态值转换
- 捕捉 svg 动态:定位错误