十八和谐综合广场

关于Pym.js

最新版本:1.3.2(发布于2018年2月13日)

在响应页面中使用iframe可能会令人沮丧。它’制作iframe很简单’宽度跨度为容器的100%,但是调整高度很难— 特别是如果iframe的内容根据页面宽度(例如,由于文本换行或媒体查询)或iframe中的事件而更改高度时。

Pym.js响应式嵌入和调整iframe的大小(宽度 高度)在其父容器中。它还绕过了常见的跨域问题。

用例: NPR Visuals团队使用Pym.js将少量自定义代码段(图表,地图等)嵌入到我们的CMS中,而不会引起CSS或JavaScript冲突。请参阅此示例。

在版本中1.3.0 我们添加了可选的滚动跟踪支持。了解它这里.

1.3.2 是重要的安全版本。我们建议所有人尽快更新到1.3.2。 更多信息这里.

获取Pym.js

使用Pym.js CDN

在大多数情况下,我们建议您使用最新的稳定版本Pym.js 托管在我们的内容交付网络(CDN)上,网址为pym.nprapps.org 而不是直接下载它。我们将使CDN版本保持最新,以便我们可以修复错误并添加新功能,而您无需进行任何更改。详细了解我们的版本控制策略。

我们建议使用https,但不安全http 如果需要,还支持该协议。

下载Pym.js

使用NPM安装

如果您使用NPM 要管理您的Javascript依赖项,则可以通过运行以下命令安装Pym.js:

npm安装pym.js

使用Bower安装

如果您使用凉亭 要管理您的Javascript依赖项,则可以通过运行以下命令安装Pym.js:

凉亭安装pym.js

无法在CMS中加载Pym.js吗?

了解有关pym-loader.js的信息.

要求/假设

  • Pym.js 不需要jQuery或任何其他库。一些示例在子页面上使用jQuery以获得不相关的功能。
  • 如果你’将iframe嵌入代码粘贴到CMS或博客软件中,请确保允许您嵌入HTML和JavaScript。一些CMS(例如WordPress)可能会将标签剥离。
  • 父页面和子页面不必位于同一域中。如果不是,则子网址应完全合格,例如,/pym.js/examples/graphic/child.html
  • Pym.js 不能用来处理在父级上嵌入多个子帧的情况。十个或更少是一个很好的经验法则。

浏览器支持

Pym.js 经过测试:

  • Internet Explorer 9、10(Windows 7),11(Windows 8.1)
  • Chrome 32(Mac 10.9)
  • Chrome 51(Mac 10.11)
  • Firefox 26(Mac 10.9)
  • Firefox 47(Mac 10.11)
  • Safari 7(Mac 10.9)
  • Safari 9(Mac 10.11)
  • iOS 7 Safari
  • Android 5.1浏览器

不支持早于9的Internet Explorer版本。如果您想了解有关我们的测试和测试策略的更多信息,请查看回购中的文档。这里.

用法

调整浏览器窗口的大小以查看实际响应情况。

在父页面上(您在哪里’重新放置iFrame)

  • 用唯一的ID命名包含的div(或任何其他块级元素)。
  • 请勿在容器div上使用任何填充或边框。这将抛出pym的高度计算。如果您需要在容器周围使用填充或边框,请将其包裹在另一个div中并在该处应用。
  • 包括Pym.js. 每页仅一次,无论您将拥有多少个iframe。
  • 创建一个new pym.Parent(parent_id, child_url); 对于 响应式iframe。 (Pym将生成实际的iframe元素。)
  • 可选:要过滤传入的邮件域,您可以传入正则表达式。例如:pym.Parent('example', 'child.html', { xdomain: '\\*\.npr\.org' });
<div id="example"></div>
<script type="text/javascript" src="/pym.v1.min.js"></script>
<脚本>
    var pymParent = new pym.Parent('example', 'child.html', {});
</脚本>

同一父页面上有多个嵌入

你不’不必对子页面做任何特殊的事情,但是您确实需要记住父页面的几件事:

  • 每个嵌入的孩子都需要一个唯一的div ID(<div id="example-1">, <div id="example-2">等)。
  • 包括Pym.js 只要一旦 在页面上。
父页面上需要HTML
<div id="example-1"></div>
<div id="example-2"></div>
<script type="text/javascript" src="/pym.v1.min.js"></script>
父页面上需要Javascript
<脚本>
var pymParent = new pym.Parent('example-1', 'child-1.html', {});
var second = new pym.Parent('example-2', 'child-2.html', {});
</脚本>

在子页面上(您要嵌入的内容)

  • 包括Pym.js.
  • 创建一个new pym.Child();.
  • 可选:如果iframe的内容是动态的,则需要传递一个渲染函数,如下所示:pym.Child({ renderCallback: myFunc }); 当页面加载时将调用此函数一次,并在调整窗口大小时再次调用此函数。
  • 可选:您可以传递数毫秒的时间来启用以该速率自动更新高度(除了onload和onresize事件之外)。例如:pym.Child({ polling: 500 });.
  • 可选:如果您需要更好地控制调整大小事件,则可以调用pymChild.sendHeight() 在任何时候强制iframe更新其大小。

示例:基本嵌入

在最简单的示例中,我们有一个更改格式(通过CSS媒体查询)的HTML表。 iframe的高度调整为内容onload和onresize的高度。

子页面需要Javascript
var pymChild = new pym.Child();

示例:页面调整大小时调用函数

如果子页面的各部分需要根据新的宽度重新绘制,这可能很有用。 (例如,由D3生成的图形不会自行拉伸或重排。)

子页面需要Javascript
function drawGraphic(width) {
    ...
}

var pymChild = new pym.Child({ renderCallback: drawGraphic });

示例:手动调整大小事件

如果您具有动态内容,并且需要更好地控制调整大小事件,则可以调用pymChild.sendHeight() 在子窗口中随时强制iframe更新其大小。例如,假设您有一个测验,并且当某人选择答案时页面的内容就会改变,从而影响页面’的高度:

子页面需要Javascript
function check_answer(e) {
    //高亮正确答案
    ...

    //将更新的高度发送给父级
    pymChild.sendHeight();
}

$('.question').find('li').on('click', check_answer);

var pymChild = new pym.Child();

示例:在iframe中跟踪链接后调整大小

如果iframe中有指向其他页面的链接,则可以通过在每个页面中明确设置子ID来保持自动调整大小。

每个子页面都需要Javascript
var pymChild = new pym.Child({ id: 'example-follow-links' });
                        

发送自定义iFrame事件

虽然不是最初的目的,Pym.js 也可以用于在iframe父级和子级之间发送和接收通用事件数据。一个简单的,类似于jQuery的事件绑定模型用于支持此消息传递。

在下面的示例中,单击父容器中的链接会将子框架导航到新位置。

父页面上需要Javascript
var pymParent = pym.Parent('example', 'child.html', {});

document.getElementById('myLink').addEventListener('click', onLinkClick);

function onLinkClick(e) {
    e.preventDefault();

    pymParent.sendMessage('navigate', e.target.href);
}
子页面需要的Javascript
var pymChild = new pym.Child();

pymChild.onMessage('navigate', onNavigateMessage);

function onNavigateMessage(url) {
    window.location.href = url;
}

注意,也可以执行相反的方案。孩子们可以向父母发送相同的消息发信息() 功能。

从孩子导航到父母的快捷方式

由于滚动和导航父窗口是非常普遍的需求,因此这些操作有一些快捷方式,不需要您实现自己的事件。

滚动和导航父级的代码
pymChild.scrollParentTo('about');
pymChild.navigateParentTo('/nprapps/pym.js');

开始于v1.1.0 我们提供了一个新的快捷方式,该快捷方式允许子级将父级滚动到子级文档中的给定位置。您可以传递相对于子页面所需的偏移量,也可以使用帮助程序函数将该子页面中元素的ID传递给它

将父滚动到子位置的代码

// download是子页面上现有HTML元素的ID
pymChild.scrollParentToChildEl('download');
pymChild.scrollParentToChildPos(1000);

这里 您可以看到一个实际使用的新滚动快捷方式的示例。

这个怎么运作

Pym.js 库和一小段javascript注入到父页面上。这段代码会将iframe写入您选择的容器中的页面。Pym.js 实际上会使用新创建的iframe替换容器的内容,因此最好从一开始就使用空容器,以免出现意外情况。对iframe的请求’的内容包括用于initialWidth, childId 子页面的parentUrlparentTitle 父页面的的initialWidth 允许孩子在加载时立即知道其大小,因为在iOS中,子框架无法准确确定其自身的宽度。的childId 允许将多个子级嵌入到同一页面上,每个子级都有与父级的自身通信。

子页面还包括Pym.js 和它自己的javascript。它初始化与父级之间的跨iframe通信,呈现任何动态内容,然后通过以下方式将计算出的子级高度发送给父级postMessage。收到此消息后,父级会调整包含的iframe的大小,从而确保子级的内容始终可见。

父页面还注册了调整大小事件。任何时候,父母都会通过以下方式将新的容器宽度发送给每个孩子postMessage。孩子重新提交其内容并发回新的身高。

可以将其他参数传递给父对象(标题, ID, 名称,...)通过配置对象,然后将该对象作为属性应用于生成的iFrame。这是一个变化的列表,因此最好检查一下API文档 获取最新的详细列表

自动初始化Pym.js

某些CMS会阻止自定义Javascript嵌入到页面中。为了允许pym支持这些环境,可以通过以下方式对其进行初始化数据- 属性。这将pym的使用限制为简单情况,但对于许多用户来说仍然足够。

(NPR会员站:使用加载程序变通办法以使其在Core Publisher中正常工作.).

父页面上需要HTML
<div data-pym-src="child.html">Loading...</div>
<script type="text/javascript" src="/pym.v1.min.js"></script>

开始于v1.1.0 您只需在父配置参数前面加上前缀即可将配置参数作为HTML数据属性传递数据-pym-。要检查所有可用的父配置参数,请查看API文档这里

<div data-pym-src="child.html" data-pym-allowfullscreen>Loading</div>
<script type="text/javascript" src="/pym.v1.min.js"></script>

pym-loader.js:Pym.js加载器

一些内容管理系统阻止将自定义Javascript嵌入到页面中,而另一些使用睡衣 加载内容,还有其他人使用需求JS 加载库。以来Pym.js 被设计为一个库,支持使用AMD公司普通JS 我们遇到了某些CMSes场景Pym.js 在某些情况下损坏或根本没有加载。

这就是为什么我们创造了pym-loader.js,这是一个额外的脚本,充当包装程序处理所有棘手的细节,以成功加载Pym.js 在许多常见情况下。pym-loader.js 是在与开发人员进行了深思熟虑和讨论之后开发的Pym.js.

包含pym-loader.js 在您的页面上自动并立即初始化所有Pym.js已启用iframe 元素。当通过脚本 tag in environments that use RequireJS and it gracefully handles the complexities of `pjax` navigation.

pym-loader.js 可以解决到目前为止我们遇到的合理数量的边缘用例,我们希望它也可以对其他人有用。但是,我们无法涵盖所有 情况。将来,“一对一”解决方案可能无法正常工作,我们可能需要针对特定 的边缘情况释放特定的装载机。但是至少Pym.js 库将与这些极端情况保持隔离。

如果您对CMS拥有合理的控制权Pym.js 实施中,我们建议原始纳入Pym.js 如我们的示例所示。如果您无法控制CMS,则说明加载时遇到问题Pym.js 或者只是希望对将来的CMS更改有更多的保护,那么您可以使用加载程序脚本。

父页面上需要HTML
<p data-pym-src="child.html">Loading...</p>
<script type="text/javascript" src="/pym-loader.v1.min.js"></script>

这里 你可以看到一个例子pym-loader.js 实际使用的页面require.js 加载其JavaScript资产

获取Pym.js加载器

使用Pym.js CDN

在大多数情况下,我们建议您使用最新的稳定版本Pym.js 托管在我们的内容交付网络(CDN)上,网址为pym.nprapps.org 而不是直接下载它。我们将使CDN版本保持最新,以便我们可以修复错误并添加新功能,而您无需进行任何更改。详细了解我们的版本控制策略。

我们建议使用https,但不安全http 如果需要,还支持该协议。

下载pym-loader.js

Pym状态自定义事件

开始于v1.2.0 我们添加了可以监听的自定义事件,以便确定内部发生的一些关键事件Pym.js.

我们添加了两个自定义事件,其中一个pym-loader.js 还有一个里面Pym.js.

  • pym-loader:pym已加载 &rr该事件在加载程序完成加载时发出信号Pym.js。您可以按照以下示例进行收听。
  • document.addEventListener('pym-loader:pym-loaded', function (e) {
        console.log("pym-loaded event fired");
        console.log(pym);
    }, false);
    
  • pym:pym初始化 &rr此事件表示何时Pym.js 已完成其自动初始化。您可以按照以下示例进行收听。
  • document.addEventListener('pym:pym-initialized', function (e) {
        console.log("pym-initialized event fired);
        console.log(pym.autoInitInstances.length);
    }, false);
    

注意:Pym.js 从那时开始,在页面上加载时执行autoInitPym.js 本身仍然无法到达,我们不提高pym:pym初始化 那么事件。您可以随时调用pym.autoInit() 手动从父母那里,这将永远提高pym:pym初始化. For example pym-loader.js 这样做是为了方便和与多个CMS配置兼容,其中Pym.js 在野外使用。

Pym可选节流滚动跟踪

开始于v1.3.0 我们在中添加了该选项Pym.js 让父级包括滚动跟踪,并在自定义iframe事件中将视口和iframe位置发送给子级视口iframe位置.

为了Pym.js 要添加滚动跟踪,您需要将config参数传递给父级。

<div id="example"></div>
<script type="text/javascript" src="/pym.v1.min.js"></script>
<脚本>
    var pymParent = new pym.Parent('example', 'child.html', {trackscroll: true});
</脚本>

滚动受到限制,因此我们不会向孩子发送过多的消息。默认的油门时间是100ms,但是您可以根据需要进行更改,如下所示:

<div id="example"></div>
<script type="text/javascript" src="/pym.v1.min.js"></script>
<脚本>
    var pymParent = new pym.Parent('example', 'child.html', {trackscroll: true, scrollwait: 500});
</脚本>

一旦Pym.js 父级配置为跟踪滚动,每次在父页面上滚动更改时,它将向子级发送一个自定义iframe事件,该消息视口iframe位置 包含以下信息,以空格分隔:

  • 视口的宽度和高度。
  • iframe的顶部,左侧,底部和右侧位置。

这将是孩子侦听该信息所需的代码:

var pymChild = new pym.Child();

pymChild.onMessage('viewport-iframe-position', onScroll);

function onScroll(parentInfo) {
    console.log(parentInfo)//将显示例如:874 776 1091 8 1673 866
}

有了这些信息,孩子就可以获得计算当前视口上是否有其元素之一并相应执行所需操作所需的所有信息。 (即延迟加载视觉资产)。

这里 您可以看到一个实际的新滚动跟踪示例。在示例中,我们添加了一个小的跟踪器库,该库可以进行计算以验证元素是否在视口中,并在可见时切换元素的背景。

获取父母的位置信息

开始于v1.3.1 我们为孩子增加了一个新功能Pym.js 为了能够要求父母将有关当前视口和iframe位置的信息发送给孩子。

这解决了通过lazyloading加载子页面的初始加载的问题,在该问题中我们可能正在跟踪父页面上的滚动,但是由于尚无滚动事件,因此子页面尚不具有iFrame在父页面上的位置信息。

var pymChild = new pym.Child();
pymChild.onMessage('viewport-iframe-position', function(parentInfo) {
    console.log(parentInfo);
});
pymChild.getParentPositionInfo();

借助这一新功能,孩子可以在加载时请求父母的位置信息并采取相应的行动。

在野外的Pym.js

执照

麻省理工学院