Подтвердить что ты не робот

Создайте встроенный 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

4b9b3361

Ответ 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, как в этом сообщении