JavaScript function is loaded via Ajax but not executed? - javascript

I have different websites that have the same data protection. So that the text does not have to be changed every time on all pages, there is a file on another server that is integrated via Ajax.
There is a part where you can set an opt-out and the domain of the respective page must be stored there.
I don't want to get tracked!
<script type="text/javascript">
document.getElementById("setOptOut").addEventListener('click', function(e) {
e.preventDefault();
var redirect = 'https://' + window.location.hostname + '/privacy';
var url = encodeURIComponent(redirect);
location.href = url;
});
</script>
The code above which is in an HTML file is loaded successfull via Ajax into the document of the web page, but when I click on the link the function is not executed.
If I call the HTML file directly on the server, everything works as expected. Why doesn't it work with Ajax?

Found this good example: https://subinsb.com/how-to-execute-javascript-in-ajax-response/
I used eval() to make the code in the AJAX response execute.

Related

Passing Javascript variables in URL

I am trying to pass a javascript variable to a php page via the URL. The code below triggers the php page but it doesn't get the variable. I have written the code using window.location.href and that works fine, the problem is doing it that way it loads the tracker.php page.
Below is my code.
<script type="text/javascript">
var siteId = "VT0013";
</script>
<script type="text/javascript" src="http://www.domainame.com/tracker.php?siteId="+ siteId ;>
</script>
PHP Page
$siteId = $_GET["siteId"];
Once I get the siteId I email the result as a test this works fine, except I am not getting the value of siteId. When using this same code with window.location.href it all works fine.
I'm guessing that since this is called tracker.php, you actually just need to hit this URL? If that's the case, consider using the Beacon API.
navigator.sendBeacon('https://example.com/tracker.php' {
siteId: 'VT0013'
});
This results in an HTTP POST request, but that's generally better for this anyway. You won't have to worry about caching. Also, the Beacon API will still work even if the request hasn't finished and the page is being unloaded.
If you actually do want to dynamically loads JavaScript instead, a current way to do that is to use import().
const siteId = 'VT0013';
await import (`https://example.com/tracker.php?siteId${encodeURIComponent(siteId)}`);
Finally, if you need to dynamically load this JavaScript and that script needs to run in the context of the rest of the page (i.e., not a module) then the best thing to do is inject a new script tag: https://stackoverflow.com/a/8578840/362536
No matter what you do, make sure you're escaping the data used in your URLs and in your HTML.
You can just do a quick XHR request if you want older browser support without polyfills:
var siteId = 'VT0013';
var xhr = (window.XMLHttpRequest) ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP');
xhr.open('GET', 'http://www.domainame.com/tracker.php?siteId=' + encodeURIComponent(siteId));
xhr.send();
This is just an alternate solution, #Brad's answer should be accepted.
You need to use document.write to write any HTML that contains JavaScript variables:
<script type="text/javascript">
var siteId = "VT0013";
document.write('<script type="text/javascript" src="http://www.domainame.com/tracker.php?siteId='+encodeURIComponent(siteId)+'">
<\/script>')
</script>
This is the equivalent of writing
<script type="text/javascript">
var siteId = "VT0013";
</script>
<script type="text/javascript" src="http://www.domainame.com/tracker.php?siteId=VT0013"></script>
Edited to properly escape JavaScript variable.
Please note that it is not advisable to use document.write to load scripts from a third-party domain because Google Chrome might choose not to load the script if the connection is too slow. See https://developers.google.com/web/updates/2016/08/removing-document-write.
If the script can be loaded asynchronously, I recommend this method instead because it will not slow down the HTML parser:
<script>
var siteId = "VT0013";
(function(d, s){
s = d.createElement("script");
s.src = "http://www.domainame.com/tracker.php?siteId="+encodeURIComponent(siteId);
d.getElementsByTagName("head")[0].appendChild(s);
})(document)
</script>

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
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";
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
Here's a full functional simple widget expample project I wrote in cloud9 (online IDE) with javascript, please feel free to request an access if you want to edit it, viewing is publicly available (for registered users - registration is free).
sources:
https://ide.c9.io/nmlc/widget-example,
result:
https://widget-example-nmlc.c9users.io/index.html
As for the question about how do they do it:
It seems that zopim builds their widgets gradually on the client side, defining and requiring basic modules (like these __$$__meshim_widget_components_mobileChatWindow_MainScreen), which are consist from submodules and then process everything with __$$__jx_ui_HTMLElement builder which creates HTML elements and appends them to provided parent nodes. All that compiles to the resulting HTML of the chatbox. Btw, judging by the names of some components, it seems, they build their widgets with some "meshim" library, but I have never heard of this library.
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()
This, I guess, is the place where zopim service creates an iframe for their widgets. I'm not sure why they are using document.write instead of appendChild (document.write drops event bindings), but I have implemented both versions - they are pretty much the same except setIframeContents and addHtmlElement functions.
Hope someone will find this useful :).
1) There are many different ways to load content to iframe. Iframe have isolated content. iframe that you put in host page, does not have src, because of browser secure politic, you can't simply load content from other domains. But you can load js from other domain.For this porpuse you need usw JSONP
2) to share cookies with host page and widget iframe, you need use postMessage api like in this post

PhoneGap load local page inside HTML

I tried to load a page inside my phonegape aplication with Jquery .load() but it doesn't work since it's not on a server and it's on local machine. When I'll upload the app on build. phonegape my page will still be included on the www folder. How can I load a page inside a div ?
This is not working
<script>
$(".form-control2").change(function(){
$(".plan_mese4").load("select_mese.html");
});
</script>
If I use http it's working but i don't need that since my file is local and not on a server.
edit*
Right now i have my app on desktop, i also compiled it with phonegap and .load() it's not working since the file is local. It only works if i put my file on a server and i load it from there but i don't want that since the request take more time.
thnx to Quentin i found that i can use the filepath to make an ajax call even if it's local. So i did it like this if anyone else needs it. I get the url location in my case file:///E:/rezerv.city/www/local.html?id=114&tip=5and i remove the local.html?id=114&tip=5.html part and i add what i need in my case select_mese.html.
$(".form-control2").change(function(){
var url =window.location.href;
url = url.substring(0, url.lastIndexOf("/") + 1);
$(".plan_mese4").load(url +'index.html');
});
in my app I'm use:
<div id="loadExternalURL" class="site"></div>
document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady() {
$('#loadExternalURL').load('http://www.site.com.br');
$.ajax({
dataType:'html',
url:'http://www.site.com.br',
success:function(data) {
$('#ajax').html($(data).children());
}
});
}
It works for me.

JQuery / Ajax - update URL without refreshing the webpage - should be compatible with IE8 and IE9

When I first load my webpage, it loads to this URL:
/default/
Now, when I click the "nextPost" button on the screen (which has an attribute called data-nextPostNumber), this is the code which I have:
event.preventDefault();
var nextPost = $(this).attr('data-nextPostNumber');
$("body").load("/default/?postNumber=" + nextPost);
So this loads the URL (assuming that nextPost=2)
/default/?postNumber=2
However, this was loaded using ajax so the actual URL in the URL bar is still
/default/
What I want to do is get the GET variables in the URL which was loaded through ajax. I have this code (which gets the GET variables in the URL and puts them in a dictionary called params):
function getQueryParams(qs) {
qs = qs.split("+").join(" ");
var params = {},
tokens,
re = /[?&]?([^=]+)=([^&]*)/g;
while (tokens = re.exec(qs)) {
params[decodeURIComponent(tokens[1])]
= decodeURIComponent(tokens[2]);
}
return params;
}
But this code just gets the GET variables in the URL which is in the URL bar - not the URL which was loaded using Ajax. So, is there a way for me to take the URL which was loaded using Ajax and place that URL in the URL bar? If not, is there any way for me to solve my issue? Please note that I need it to be compatible with IE8 and IE9.
You can use the new History API method pushState:
<input type="button" value="Post #2"
onclick="history.pushState(null, 'MyWebsite Post #2', 'http://mywebsite.com/?postNumber=2');" />
When you click this button, the location will change to http://mywebsite.com/?postNumber=2 and then you can call your getQueryParams function as follows:
getQueryParams(location.search);
The pushState will NOT work if you open the page as a file, in another words, it must come from a webserver (it works with localhost)

Load another page in jquery tooltip

My html code is:
<div class="ui-widget photo">
<div class="ui-widget-header ui-corner-all">
<h2>St. Stephen's Cathedral</h2>
<h3>Vienna, Austria</h3>
</div>
<div id="result"></div>
</div>
My Javascript code is:
$(function () {
$(document).tooltip({
items: "[href]",
content: function () {
var element = $(this);
if (element) {
var text = element.text();
var link = element.attr('href');
// alert(link);
return "<img class='map' alt='" + text +
"' src='http://maps.google.com/maps/api/staticmap?" +
"zoom=11&size=350x350&maptype=terrain&sensor=false&center=" +
"Vienna, Austria" + "'>";
}
}
});
});
This thing is given here :
jQuery tooltip
But Now I want to load another page from another url say : www.google.com in this tooltip.
what I am doing is:
I am putting .load() function in this content section so that I can get response html and return it into the tooltip
Here is my code but its not working I am getting nothing in response ...
$(function () {
$(document).tooltip({
items: "[href]",
content: function () {
$('#result').load('http://stackoverflow.com/', function (response, status, xhr){
var responseText = response;
});
var element = $(this);
if (element) {
var text = element.text();
var link = element.attr('href');
// alert(link);
return responseText;
}
}
});
});
$.load('http://stackoverflow.com');
Won't return anything because you're trying to load another web site. That's against how AJAX works.
From jQuery docs:
The .load() method, unlike $.get(), allows us to specify a portion of
the remote document to be inserted.
It allows the user to load a file on the same domain, not external ones, for security reasons.
If you observe this fiddle with firebug opened you can see that the call will return header 200 OK but will not load anything due to these restrictions.
To achieve what you want you could make a local file that fetches the desired page, then make an ajax call to it, instead of a directly calling the web site.
A simple example of using local php file to get the page.
Create a local file, I'll call it foo.php
<?php
echo file_get_contents($_GET['url']);
// this will echo contents of given url
?>
Mind, this is only an example code and is not for serious use
Then call it like this
$("#container").load("foo.php?url=google.com");
This is because you are trying to make a CORS (Cross Origin Resource Sharing) request.
And because of security concerns such requests are not entertained by browsers and servers unless the server returns Access-Control-Allow-Origin header with the requesting domain acceptable to it.
To know when does CORS come into play read this: http://en.wikipedia.org/wiki/Same_origin_policy#Origin_determination_rules
To know more about CORS read the following article http://www.html5rocks.com/en/tutorials/cors/.
To test if the server supports CORS you can use the following website: http://client.cors-api.appspot.com/client
An alternative would be to make a PHP proxy on your server and then make a CORS request through that proxy.
Here is a tutorial for creating your own PHP proxy http://jquery-howto.blogspot.in/2009/04/cross-domain-ajax-querying-with-jquery.html

Categories

Resources