用JS来修改网页属性
昨天要解决一个 bug,在手机端网页中的视频框溢出。
问题由来
要在网页中插入视频时,现在一般的做法是,把视频托管在第三方服务,第三方服务会提供一段插入视频的代码。比如说 POLYV,会提供这样一段代码:
<script src='//player.polyv.net/script/polyvplayer.min.js'></script>
<div id='plv_a49c512d573f5e4b9444e1c90ce88080_a'></div>
<script>
var player = polyvObject('#plv_a49c512d573f5e4b9444e1c90ce88080_a').videoPlayer({
'width':'600',
'height':'338',
'vid' : 'a49c512d573f5e4b9444e1c90ce88080_a'
});
</script>
第一段代码是引入 POLYV 的播放器插件,第二段是该视频的插入位置,代一个随机的视频id,第三段是生成播放视频的 JavaScript 代码。
这是 POLYV 提供的代码,只需要贴到网页里,就可以把视频引入了。注意到第三段代码里,对视频的播放框设定了宽度和长度。在一般的网页浏览是没问题的,当在小屏幕浏览时,比如说手机里,视频的宽度无法自适应,仍然是600宽,就会溢出。
解决思路
这个问题的由来,其实就是这段代码里限制死了视频播放框的尺寸,最简单的解决办法,就是在这段代码里加一句
'max-width':'100%',
但是这个解决办法不是负责任的办法。因为这段代码是由 POLYV 提供,然后由用户贴到文章里的。要求用户每次贴视频的时候都修改代码,这简直是不可能的。而且从产品的角度来说,这是一个 bug。
所以,必须要在现有的条件下来解决。换言之,就是要想办法为视频播放框加一个属性 max-width:100%
。
问题研究
第一步,当然是要分析网页的 HTML 代码。用 Chrome 的 inspect 查看。
在桌面端,最后生成的代码是
<div id='plv_a49c512d573f5e4b9444e1c90ce88080_a'>
<object type='application/x-shockwave-flash' data="//player.polyv.net/videos/player.swf" id="a49c512d573f5e4b9444e1c90ce88080_a" width="600" height="338" class="polyvFlashObject">
//更多代码
</object>
</div>
看起来问题很简单,于是我就在 css 文件里为 object
加了一条属性
object {
max-width:100%;
}
在 Chrome 中切换到手机界面,发现起作用了,视频框被限制在了 100% 的宽度,没有再溢出。问题解决了?
当我刷新时,发现视频再次溢出了。再看网页的代码,发现竟然没有了 object
这个标签!代码变成了
<div id='plv_a49c512d573f5e4b9444e1c90ce88080_a'>
<div id='containera49c512d573f5e4b9444e1c90ce88080_a' style="height: 338px; width: 600px; position: relative; max-width: 100%;">
<iframe name="polyvPlayer" //... >
//更多代码
</iframe>
</div>
</div>
细想之下,肯定是 POLYV 的播放器作的手脚,在桌面端,播放器用的是 flash,在手机端,就是嵌入一个 iframe
来实现。两种形式,最后呈现的 HTML 代码是不一样的。
经过在 chrome 里反复测试,只有在 id='containera49c512d573f5e4b9444e1c90ce88080_a'
这一层加入宽度限制的属性,才能把视频播放框的宽度限制住。但这个 id 是不确定的,这样就没办法提前在 CSS 文件里作限制。只能用 JavaScript 了。
现在的问题变成:
- 在网页生成之后,找出包裹视频的那个
id
; - 给这个
id
加一个限制宽度的属性。
解决方案一
注意到这一段代码
<script>
var player = polyvObject('#plv_a49c512d573f5e4b9444e1c90ce88080_a').videoPlayer({
'width':'600',
'height':'338',
'vid' : 'a49c512d573f5e4b9444e1c90ce88080_a'
});
</script>
定义了一个变量 player
,里面包含了一个 vid
的属性。
而我要找的 id
是 containera49c512d573f5e4b9444e1c90ce88080_a
,实际上就是由 'container' + vid
组成的。这就好办了。先在网页的 console 里先试试。
var id = "#container" + player.vid
$(id).css('max-width', "100%")
起作用了。
只要在网页加载之后,再运行这两行 JavaScript 代码就可以了。
最后的代码是这样的:
$(document).on('turbolinks:load', function() {
var id = "#container" + player.vid;
$(id).css('max-width', "100%");
}
解决方案二
上面的解决方案有一个问题:当一个页面插入两个视频的时候,第一个视频就失效了。
当用相同的代码插入两个或两个以上视频时,player
这个变量指代的其实只是最后一个视频。也就是说,player
只是一个中间变量,依靠中间变量来修改是不稳妥的。
怎样才更稳妥呢?最好能**找出网页中所有以 container
开头的 id
**。
这里要用到 JQuery 的一个模糊查找功能。
The [attribute^=value] selector selects each element with a specific attribute, with a value beginning in a specific string.
$(document).on('turbolinks:load', function() {
var vid=$('div[id^=container]');
if (vid.length > 0) {
for (var i = 0; i < vid.length; i++) {
$(vid[i]).css('max-width', '100%');
}
};
}
这里 $('div[id^=container]')
的意思就是提取出所有带有以 container
开头的 id 的 div 标签,结果是一个 array,然后再通过一个循环,把它们都加一个 css 样式。
总结
之前除了用 JavaScript 的插件,很少自己通过写 JS 代码来直接解决问题。这一次的解 bug 过程让我对 JS 的使用有了进一步的理解。主要学到的知识点包括
- 在网页加载之后,用 JS 来修改网页;
- 为带有某个 id 的标签增加 CSS 样式;
- JQuery 的模糊查找功能。