Создайте встроенный JavaScript на странице перекрестного домена хоста, на который не влияет CSS-страница узла?
Большинство виджета 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>
Затем при загрузке вашей страницы этот 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
, т.е. присоединенного URL.
Обновление: вот script Я использую для загрузки моего кода виджетов на сторонний веб-сайт:
<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>
Я хочу, чтобы CSS сайта, на котором интегрирован виджет GWT, не должен влиять на CSS виджета GWT. Я буду препятствовать тому, чтобы CSS-страница хоста влияла на CSS моего виджета GWT.
Примечание. Я хочу получить доступ к веб-узлу хоста из моего виджета GWT.
Домен главной страницы - www.example.com, а домен iframe - www.widget.com. Я также хочу установить файлы cookie домена хоста из iframe.
Какова процедура построения виджета, работающего на такой структуре? Как настроено содержимое iframe? Есть ли образец для этого? Как я могу это сделать с помощью GWT
Ответы
Ответ 1
Я не знаю 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 next sibling, i.e. after the script.
scriptElement.parentNode.insertBefore(iframe, scriptElement.nextSibling);
// rest of the code
</script>
Затем введите счет онлайн, используя JSONP (см. Что такое JSONP?, например:
// 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 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 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 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 body.
iframe.contentWindow.document.body.appendChild(div);
}
// Create a script.
var script = document.createElement("script");
// Set script src attribute to API URL + JSONP callback parameter.
// It makes browser send HTTP request to the API.
script.src = url + "?callback=callback";
Ответ 2
EDIT:
если вы хотите, чтобы на ваш виджет не влиял какой-либо 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.
как это все ваши кланы insde рамки не будут затронуты любым классом извне.
чтобы получить доступ к чему-либо за пределами этого iframe, вы можете использовать методы jsni. это будет работать только в том случае, если домен вашего iframe и третьего partysite одинаковый. иначе youve использовать window.postMessage
:
public native static void yourMethod() /*-{
$wnd.parent.someMethodFromOutsideTheIframe();
}-*/;
EDIT2:
используя сниппет сверху, убедитесь, что ваш виджет не влияет на какой-либо css из главной страницы.
для получения URL-адреса хост-страницы внутри виджета просто добавьте эту функцию:
private native static String getHostPageUrl() /*-{
return $wnd.parent.location.hostname;
}-*/;
EDIT3:
поскольку вы находитесь на двух разных доменах, вам нужно использовать 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
класс gwt с onmoduleload: http://pastebin.com/QjDRuPmg
Ответ 3
Здесь полный функциональный простой проект расширения виджета, который я написал в 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
builder, который создает элементы HTML и добавляет их к предоставленным родительским узлам. Все, что компилируется в результате HTML-чата. Кстати, судя по именам некоторых компонентов, похоже, они строят свои виджеты с некоторой библиотекой "meshim", но я никогда не слышал об этой библиотеке.
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
и addHtmlElement
.
Надеюсь, кто-то найдет это полезным:).
Ответ 4
1) Существует множество способов загрузки содержимого в iframe. Iframe имеет изолированное содержимое. iframe, который вы размещаете на главной странице, не имеет src, из-за браузера, защищенного политикой, вы не можете просто загружать контент из других доменов. Но вы можете загрузить js из другого домена. Для этой порции вам понадобится JSONP
2), чтобы обмениваться файлами cookie с главной страницей и виджетами iframe, вам нужно использовать postMessage api, как в этом сообщении