可嵌入网站的大多数javascript小部件使用以下结构。首先你嵌入一个像这样的代码:
<script type="text/javascript">
window.$zopim||(function(d,s){var z=$zopim=function(c){
z._.push(c)},
$=z.s=d.createElement(s),
e=d.getElementsByTagName(s)[0];
z.set=function(o){
z.set._.push(o)
};
z._=[];
z.set._=[];
$.async=!0;
$.setAttribute('charset','utf-8');
$.src='//v2.zopim.com/?2342323423434234234';
z.t=+new Date;
$.type='text/javascript';
e.parentNode.insertBefore($,e)})(document,'script');
</script>
然后,在加载页面时,此脚本会创建一个这样的html结构:
<div class="widget-class">
<iframe src="about:blank">
// the content of the widget
</iframe>
</div
我在许多聊天服务中看到了相同的结构,例如:
https://en.zopim.com/
http://banckle.com/
https://www.livechatinc.com/
所有人都有共同点,他们的iframe没有src
,即附加了一个网址。
更新:这是我用来将我的小部件代码加载到第三方网站的脚本:
<script type="text/javascript">
(function(d){
var f = d.getElementsByTagName('SCRIPT')[0], p = d.createElement('SCRIPT');
window.WidgetId = "1234";
p.type = 'text/javascript';
p.setAttribute('charset','utf-8');
p.async = true;
p.src = "//www.example.com/assets/clientwidget/chatwidget.nocache.js";
f.parentNode.insertBefore(p, f);
}(document));
</script>
我希望集成GWT小部件的站点的CSS不应该影响GWT小部件的CSS。我将阻止主页的CSS影响我的GWT小部件的CSS。
注意:我也想从我的GWT小工具访问主机网站。
主页的域名是www.example.com,iframe的域名是www.widget.com。我还想从iframe设置主机域的cookie。
构建在这样的结构上运行的小部件的过程是什么?如何设置iframe的内容?那有什么模式吗?我怎么能用GWT
来做到这一点答案 0 :(得分:4)
我不了解GWT,但您可以通过简单的JavaScript轻松实现这一目标。
假设您正在创建在线计数小部件。首先,创建一个iframe:
<script id="your-widget">
// Select the script tag used to load the widget.
var scriptElement = document.querySelector("your-widget");
// Create an iframe.
var iframe = document.createElement("iframe");
// Insert iframe before script's next sibling, i.e. after the script.
scriptElement.parentNode.insertBefore(iframe, scriptElement.nextSibling);
// rest of the code
</script>
然后使用JSONP获取在线计数(请参阅What is JSONP all about?),例如:
// The URL of your API, without JSONP callback parameter.
var url = "your-api-url";
// Callback function used for JSONP.
// Executed as soon as server response is received.
function callback(count) {
// rest of code
}
// Create a script.
var script = document.createElement("script");
// Set script's src attribute to API URL + JSONP callback parameter.
// It makes browser send HTTP request to the API.
script.src = url + "?callback=callback";
然后处理服务器响应(在callback()
函数内):
// Create a div element
var div = document.createElement("div");
// Insert online count to this element.
// I assume that server response is plain-text number, for example 5.
div.innerHTML = count;
// Append div to iframe's body.
iframe.contentWindow.document.body.appendChild(div);
这就是全部。您的整个代码可能如下所示:
要插入第三方网站的代码段:
<script type="text/javascript">
(function(d){
var f = d.getElementsByTagName('SCRIPT')[0], p = d.createElement('SCRIPT');
window.WidgetId = "1234";
p.type = 'text/javascript';
p.setAttribute('charset','utf-8');
p.async = true;
p.id = "your-widget";
p.src = "//www.example.com/assets/clientwidget/chatwidget.nocache.js";
f.parentNode.insertBefore(p, f);
}(document));
</script>
服务器上的JavaScript文件:
// Select the script tag used to load the widget.
var scriptElement = document.querySelector("#your-widget");
// Create an iframe.
var iframe = document.createElement("iframe");
// Insert iframe before script's next sibling, i.e. after the script.
scriptElement.parentNode.insertBefore(iframe, scriptElement.nextSibling);
// The URL of your API, without JSONP callback parameter.
var url = "your-api-url";
// Callback function used for JSONP.
// Executed as soon as server response is received.
function callback(count) {
// Create a div element
var div = document.createElement("div");
// Insert online count to this element.
// I assume that server response is plain-text number, for example 5.
div.innerHTML = count;
// Append div to iframe's body.
iframe.contentWindow.document.body.appendChild(div);
}
// Create a script.
var script = document.createElement("script");
// Set script's src attribute to API URL + JSONP callback parameter.
// It makes browser send HTTP request to the API.
script.src = url + "?callback=callback";
答案 1 :(得分:1)
修改强>
如果你希望你的小部件不受“外部”的任何css的影响,你必须加载到iframe。
添加到您的网站以加载任何gwt项目/小部件的代码:
<iframe id="1234" src="//www.example.com/assets/Chatwidget.html" style="border: 1px solid black;" tabindex="-1"></iframe>
注意:我没有加载nocache.js,而是加载了yourwidget.html文件。 像这样你的所有条款都不会受到来自外界的任何阶级的影响。
要访问此iframe之外的任何内容,您可以使用jsni methods。这仅适用于iframe和第三方的域名相同的情况。否则你可以使用window.postMessage
:
public native static void yourMethod() /*-{
$wnd.parent.someMethodFromOutsideTheIframe();
}-*/;
<强> EDIT2:强>
通过使用上面的代码段,您可以确保您的小部件不会受到主页中任何css的影响。 要从小部件内部获取主页网址,只需添加此功能:
private native static String getHostPageUrl() /*-{
return $wnd.parent.location.hostname;
}-*/;
<强> EDIT3:强>
因为您在2个不同的域上,所以必须使用window.postMessage。 这里有一个小例子可以帮助你:
除了iframe之外,您还必须在example.com的窗口中添加一个事件侦听器,以侦听来自iframe的消息。您还可以检查消息是否来自正确的来源。
<script>
// Create IE + others compatible event handler
var eventMethod = window.addEventListener ? "addEventListener"
: "attachEvent";
var eventer = window[eventMethod];
var messageEvent = eventMethod == "attachEvent" ? "onmessage"
: "message";
// Listen to message from child window
eventer(messageEvent, function(e) {
//check for the correct origin, if wanted
//if ( e.origin !== "http://www.widget.com" )
// return
console.log('parent received message!: ', e.data);
//here you can set your cookie
document.cookie = 'cookie=widget; expires=Fri, 1 Feb 2016 18:00:00 UTC; path=/'
}, false);
</script>
从小部件内部调用此方法:
public native static void postMessageToParent(String message) /*-{
//message to sent, the host that is supposed to receive it
$wnd.parent.postMessage(message, "http://www.example.com");
}-*/;
我在pastebin上放了一个工作示例:
要插入页面的JavaScript:http://pastebin.com/Y0iDTntw
带有onmoduleload的gwt类:http://pastebin.com/QjDRuPmg
答案 2 :(得分:0)
这是我在cloud9(在线IDE)中使用javascript编写的全功能简单小部件示例项目,如果您想编辑它,请随时请求访问,查看是公开的(对于注册用户 - 注册是免费)。
来源: https://ide.c9.io/nmlc/widget-example, 结果: https://widget-example-nmlc.c9users.io/index.html
关于他们如何做的问题:
似乎zopim在客户端逐步构建其小部件,定义并要求基本模块(如__$$__meshim_widget_components_mobileChatWindow_MainScreen
),这些模块由子模块组成,然后使用__$$__jx_ui_HTMLElement
构建器处理所有内容,从而创建HTML元素并将它们附加到提供的父节点。所有这些都编译成聊天框的结果HTML。顺便说一下,从一些组件的名称来看,似乎他们用一些&#34; meshim&#34;来构建他们的小部件。图书馆,但我从来没有听说过这个图书馆。
this.dom.src='about:blank'
this.appendToParent(!0)
var H=this.iwin=this.dom.contentWindow
var I=this.idoc=r.extend(H.document)
I.write(G)
I.close()
我想,这是zopim服务为其小部件创建iframe的地方。我不确定为什么他们使用document.write而不是appendChild(document.write删除事件绑定),但我已经实现了两个版本 - 它们几乎相同,除了setIframeContents
和{{1}函数。
希望有人会发现这有用:)。
答案 3 :(得分:0)
1)将内容加载到iframe的方法有很多种。 iframe有孤立的内容。你放在主机页面的iframe,没有src,因为浏览器安全政策,你不能简单地从其他域加载内容。但是你可以从其他域加载js。对于这个porpuse你需要使用JSONP
2)与主机页面和小部件iframe共享cookie,你需要像post
一样使用postMessage api