Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create an embedded JavaScript in a Cross Domain Host Page which is not affected by the Host Page CSS?

Most javascript widget which can be embedded into a website use the following structure. First you embed a code snipped like this:

<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> 

Then, when load your page this script creates a html structure like this:

<div class="widget-class">   <iframe src="about:blank">     // the content of the widget   </iframe> </div 

I see this same structure in many chat services like:

https://en.zopim.com/  http://banckle.com/ https://www.livechatinc.com/ 

All have in common that their iframe does not have a src, i.e., an URL attached.

Update: Here is the script I use to load my widget code into a third party website:

<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>     

I want that the CSS of the site where the GWT widget is integrated should not influence the CSS of the GWT widget. I will prevent that the CSS of the host page influence the CSS of my GWT widget.

Note: I want to have access to tho host website from my GWT widget too.
The domain of the host page is www.example.com and the domain of the iframe is www.widget.com. I also want to set cookies of the host domain from the iframe.

What is the procedure of building a widget running on such a structure? How is the content of the iframe being set? Is there a pattern for that? How can I do that with GWT

like image 753
confile Avatar asked Jan 04 '16 20:01

confile


People also ask

Can JavaScript be embedded?

You can embed JavaScript in an HTML document in the following ways: As statements and functions within a <SCRIPT> tag. See the following section, "Using the SCRIPT tag". By specifying a file as the JavaScript source (rather than embedding the JavaScript in the HTML).

What is cross domain iframe?

Learn about how cross-domain iframe can be used to safely circumvent browser restrictions on scripts that process code in a different domain. Applies to: Skype for Business 2015. Web applications that interact with UCWA 2.0 resources require a cross-domain iframe for all HTTP requests sent to UCWA 2.0.


2 Answers

I don't know GWT, but you can easily achieve this in plain JavaScript.

Let's assume you're creating an online-count widget. At first, create an 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> 

Then fetch the online count using JSONP (see What is JSONP all about?), for example:

// 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"; 

Then handle server response (inside the callback() function):

// 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); 

That's all. Your whole code could look like this:

Snippet to insert into third party website:

<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 file on your server:

// 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"; 
like image 180
Michał Perłakowski Avatar answered Sep 20 '22 11:09

Michał Perłakowski


EDIT:
if you want your widget to not be influenced by any css from the "outside" you have to load into an iframe.

code to add to your website to load any gwt project/widget:

<iframe id="1234" src="//www.example.com/assets/Chatwidget.html" style="border: 1px solid black;" tabindex="-1"></iframe> 

notice: that im NOT loading the nocache.js but the yourwidget.html file. like this all your clases insde the frame wont be affected by any class from the outside.

to access anything outside ofthis iframe you can use jsni methods. this will only work if the domain of your iframe and the thirdpartysite are the same. otherwise youve to use window.postMessage:

public native static void yourMethod() /*-{      $wnd.parent.someMethodFromOutsideTheIframe();  }-*/; 

EDIT2:

by using the snippet from above you make sure that your widget is not influened by any css from the hostpage. to get the hostpage url from inside the widget simply add this function:

private native static String getHostPageUrl() /*-{     return $wnd.parent.location.hostname; }-*/; 

EDIT3:

since you are on 2 different domains, you have to use window.postMessage. here one little example to get you going:

besides the iframe you have to add a event listener to the window of your example.com, that listens for the messages from your iframe. you also check if the messages comes form the correct origin.

<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> 

From inside your widget you call this method:

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"); }-*/; 

i put a working example on pastebin:

javascript to insert into your page: http://pastebin.com/Y0iDTntw
gwt class with onmoduleload: http://pastebin.com/QjDRuPmg

like image 28
Tobika Avatar answered Sep 20 '22 11:09

Tobika