# IFrame控件开发

当表单上需要复杂的用户交互界面,平台提供的控件或者动态机制无法满足需求时,可考虑使用IFrame控件,开发者可以定制UI和交互。完整的IFrame控件设计指引可参考此处,以下将以用户评价控件为例说明IFrame控件开发要点。

# 需求分析

用户评价控件要求页面上出现5颗星星,用户可以点选星星对某项服务进行评分

# 建立主窗口

根据需求,评分控件只需要一个主窗口即可,无需弹出flyout窗口

首先新建html页面,添加流程平台前端infoplus.sdk.js (opens new window)的引用,并在onload事件中初始化主窗口,具体文档请参考

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width,initial-scale=1.0" />
        <title>评分</title>
        <script type="text/javascript" src="https://form.sjtu.edu.cn/infoplus/static/js/sdk/infoplus.sdk.js"></script>
    </head>
    <body>
        <div>
            <ul id="star"></ul>
        </div>
    </body>
    <script>
        window.onload = function () {
            InfoPlusSDK.iframe.init('https://form.sjtu.edu.cn');
        };
    </script>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# 加载页面参数

作为一个可以通用的控件,评分的星星数量应该可以由流程开发者定,并且页面可以显示每颗星星评分的具体含义。我们将星星总数设为total,将评分含义设为desc,前者是一个数字,后者是以逗号分隔的字符表示评分含义,其数量应该和星星数匹配。


function getQueryParameter(search, parameter) {
    if (search == null || search.length < 1) {
        return;
    }
    const query = search.substring(1);
    const vars = query.split('&');
    for (let i = 0; i < vars.length; i++) {
        const pair = vars[i].split('=');
        if (pair[0] === parameter) {
            return decodeURIComponent(pair[1]);
        }
    }
}

function initParams() {
    const total = parseInt(getQueryParameter(location.search, 'total'), 10) || 0;
    const descriptions =
        getQueryParameter(location.search, 'desc') != null ? getQueryParameter(location.search, 'desc').split(',') : [];
    if (total <= 0 || (descriptions.length !== total && descriptions.length !== 0)) {
        console.warn('参数错误,请核对', total, descriptions);
    }
    return { total, descriptions };
}

window.onload = function () {
    InfoPlusSDK.iframe.init('https://form.sjtu.edu.cn');
    const params = initParams();
};

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

# 创建星星

现在我们需要根据total参数和desc参数创建星星和描述。

function createStars(total, descriptions) {
    let stars = [];
    let ul = document.getElementById('star');
    for (let i = 0; i < total; i++) {
        let star = document.createElement('li');
        star.setAttribute('class', 'star');
        ul.appendChild(star);
        stars.push(star);
    }
    let text = document.createElement('li');
    text.setAttribute('id', 'text');
    text.setAttribute('class', 'text');
    ul.appendChild(text);
    return stars;
}

window.onload = function () {
    InfoPlusSDK.iframe.init('https://form.sjtu.edu.cn');
    const params = initParams();
    const stars = createStars(params.total, params.descriptions);
};

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# 交互事件

当用户的鼠标进入星星或者移出星星时应高亮或者取消高亮相应的星星,当用户点击某颗星星代表用户进行了评分,此时应该将分数作为IFrame控件属性设置,定这个属性名为score,星星的点击事件中需要调用InfoPlusSDK.iframe.setPropertyValue方法设置score属性值,具体文档请参考

设计交互时必须考虑IFrame控件当前步骤的权限,只有当有写权限时才可以交互,具体文档请参考

function createStars(total, descriptions) {
    let stars = [];
    let ul = document.getElementById('star');
    for (let i = 0; i < total; i++) {
        let star = document.createElement('li');
        star.setAttribute('class', 'star');
        ul.appendChild(star);
        stars.push(star);
        // 只有有写权限时才绑定事件
        if (InfoPlusSDK.iframe.isWritable()) {
            bindStarEvent(star, i + 1, descriptions);
        }
    }
    let text = document.createElement('li');
    text.setAttribute('id', 'text');
    text.setAttribute('class', 'text');
    ul.appendChild(text);
    return stars;
}

function bindStarEvent(star, num, descriptions) {
    star.onmouseover = function () {
        show(num, descriptions[num - 1]);
    };
    // 鼠标移出时根据当前score属性值设置星星的高亮
    star.onmouseout = function () {
        let score = InfoPlusSDK.iframe.getProperty('score') || 0;
        show(score, descriptions[score - 1]);
    };
    // 点击事件中设置控件score属性值
    star.onclick = function () {
        InfoPlusSDK.iframe.setPropertyValue('score', num);
    };
}

function show(score, text) {
    text = text || '';
    const stars = document.getElementsByClassName('star');
    for (let i = 0; i < stars.length; i++) {
        if (i < score) {
            stars[i].classList.add('light');
        } else {
            stars[i].classList.remove('light');
        }
    }
    document.getElementById('text').innerText = text;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

# 初值

表单控件加载时应该根据当前的score属性值初始化高亮星星,具体文档请参考

window.onload = function () {
    InfoPlusSDK.iframe.init('https://form.sjtu.edu.cn');
    const params = initParams();
    const stars = createStars(params.total, params.descriptions);
    const score = InfoPlusSDK.iframe.getProperty('score') || 0;
    show(score, params.descriptions[score - 1]);
};
1
2
3
4
5
6
7

# 测试

因为浏览器的安全策略问题,您的IFrame控件必须以https方式访问才能正常工作,如果在开发时不便于用https访问,可以在交大内网使用平台的ip地址以http方式访问,具体访问方式请联系leiyan获取。

# 投稿

如果您认为您开发的IFrame控件具有一定的通用性并乐于分享,欢迎发邮件投稿,通过我们的测试后,我们将会把您制作的控件放到流程平台生产服务器上供开发者使用。

# 下载

download 完整案例代码