Why can't I create my own custom component in Google Chrome 48? - google-chrome

I have built a library of custom elements using the webcomponents polyfills provided by Polymer. It works in Firefox and Safari. But it doesn't work in Chrome 48 with native component support. I can make it work if I use the polyfill code hacked to not use the native implementation...
Here is an example:
<!DOCTYPE html>
<html>
<head>
<script>
var myComp = Object.create(HTMLElement.prototype);
document.registerElement('my-comp', {prototype: myComp});
myComp.attachedCallback = function () {
console.log('my-comp attached');
}
</script>
</head>
<body>
<my-comp></my-comp>
<p> Just to check that page is loaded</p>
</body>
</html>
I should see the message in the console, but nothing is displayed. Support is enabled in Chrome (I can see that document.registerElement is native), my code is loaded and executed (the element is registered, I get a warning if I try to register it again in the console), and the callback is valid (I can call it by hand in the console).
What happens? How can I make it work?

You will make it work by attaching event handlers before registering element:
var myComp = Object.create(HTMLElement.prototype);
myComp.attachedCallback = function ()
{
console.log('my-comp attached');
}
document.registerElement('my-comp', {prototype: myComp});

Related

Integrate ts into html: uncaught ReferenceError clickbutton not defined

I try to build a simple CRUD frontend with no frameworks! I try to integrate a TypeScript file (intex.ts) into my index.html but it keeps beeing not found so that the called functions are undefined. I'm aware that browsers can't handle typescript but need javascript. I build my app before testing and all ts files get compiled. I tried integrating the compiled js file but it's not found either. All my frontend code is in directory src/public.
How do I connect my public/index.html with my public/index.ts so that the fundtions work?
relevant index.html code
<head>
<script type="text/typescript" src="index.ts"></script>
</head>
<body>
<button onclick="clickButton()">Click</button>
</body>
all index.ts code
function clickButton() {
document.getElementById("cases").innerText = "Hello Cases"
}
error i'm getting when clicking the button
index.html:18 Uncaught ReferenceError: clickButton is not defined
at HTMLButtonElement.onclick (index.html:18)
I use express in the backend and use express.static:
app.use(express.static("src/public"));
It seems to be an error caused because the function is defined outside of the global scope.
You can try to assign the function to the global window object just below of the function declaration:
function clickButton(){
...
}
window.clickButton = clickButton; // Now the function can be accessed from global scope
Also u can try to add the eventlistener on your JS file instead of using the html attribute onclick:
function clickButton(){
...
}
document.querySelector('.button-smth').addEventListener('click', clickButton);
This way you don't need to assign the function to the global scope at all, but you will need to add the class '.button-smth' (or whatever) to the html button element.
Hope this helps!
Your ts need to be compiled to js first. Then, you could possibly use it as follows -
function clickButton() {
document.getElementById("cases").innerText = "Hello Cases"
}
<head>
<script type="text/javascript" src="index.js"></script>
</head>
<body>
<button onclick="clickButton()">Click</button>
<div id="cases"></div>
</body>
Note: This is just a possible solution

jQuery "load" on webview

I'm trying to use the jQuery .load() function on a <webview/> into a Chrome Packaged App.
This is my test did with an iFrame:
$('<iframe />').attr("src", "http://example.org").load(function(){
$(this).addClass("shown");
}).appendTo('#body');
Fiddle: http://jsfiddle.net/m9ws5/1/
The problem is that when I try to use this code in my packaged app replacing <iframe/> with <webview/> it doesn't fire the load event.
I think the problem is that webview are different from iframe, how can I do?
I've found a solution using the Chrome methods:
onload = function() {
var webview = $("#webview");
webview.on("loadstop", function () {
webview.addClass("shown");
});
}
(always read documentation! https://developer.chrome.com/apps/tags/webview#methods)

Is cross-origin postMessage broken in IE10?

I'm trying to make a trivial postMessage example work...
in IE10
between windows/tabs (vs. iframes)
across origins
Remove any one of these conditions, and things work fine :-)
But as far as I can tell, between-window postMessage only appears to work in IE10 when both windows share an origin. (Well, in fact -- and weirdly -- the behavior is slightly more permissive than that: two different origins that share a host seem to work, too).
Is this a documented bug? Any workarounds or other advice?
(Note: This question touches on the issues, but its answer is about IE8 and IE9 -- not 10)
More details + example...
launcher page demo
<!DOCTYPE html>
<html>
<script>
window.addEventListener("message", function(e){
console.log("Received message: ", e);
}, false);
</script>
<button onclick="window.open('http://jsbin.com/ameguj/1');">
Open new window
</button>
</html>
launched page demo
<!DOCTYPE html>
<html>
<script>
window.opener.postMessage("Ahoy!", "*");
</script>
</html>
This works at: http://jsbin.com/ahuzir/1 -- because both pages are hosted at the same origin (jsbin.com). But move the second page anywhere else, and it fails in IE10.
I was mistaken when I originally posted this answer: it doesn't actually work in IE10. Apparently people have found this useful for other reasons so I'm leaving it up for posterity. Original answer below:
Worth noting: the link in that answer you linked to states that postMessage isn't cross origin for separate windows in IE8 and IE9 -- however, it was also written in 2009, before IE10 came around. So I wouldn't take that as an indication that it's fixed in IE10.
As for postMessage itself, http://caniuse.com/#feat=x-doc-messaging notably indicates that it's still broken in IE10, which seems to match up with your demo. The caniuse page links to this article, which contains a very relevant quote:
Internet Explorer 8+ partially supports cross-document messaging: it
currently works with iframes, but not new windows. Internet Explorer
10, however, will support MessageChannel. Firefox currently supports
cross-document messaging, but not MessageChannel.
So your best bet is probably to have a MessageChannel based codepath, and fallback to postMessage if that doesn't exist. It won't get you IE8/IE9 support, but at least it'll work with IE10.
Docs on MessageChannel: http://msdn.microsoft.com/en-us/library/windows/apps/hh441303.aspx
Create a proxy page on the same host as launcher. Proxy page has an iframe with source set to remote page. Cross-origin postMessage will now work in IE10 like so:
Remote page uses window.parent.postMessage to pass data to proxy page. As this uses iframes, it's supported by IE10
Proxy page uses window.opener.postMessage to pass data back to launcher page. As this is on same domain - there are no cross-origin issues. It can also directly call global methods on the launcher page if you don't want to use postMessage - eg. window.opener.someMethod(data)
Sample (all URLs are fictitous)
Launcher page at http://example.com/launcher.htm
<!DOCTYPE html>
<html>
<head>
<title>Test launcher page</title>
<link rel="stylesheet" href="/css/style.css" />
</head>
<body>
<script>
function log(msg) {
if (!msg) return;
var logger = document.getElementById('logger');
logger.value += msg + '\r\n';
}
function toJson(obj) {
return JSON.stringify(obj, null, 2);
}
function openProxy() {
var url = 'proxy.htm';
window.open(url, 'wdwProxy', 'location=no');
log('Open proxy: ' + url);
}
window.addEventListener('message', function(e) {
log('Received message: ' + toJson(e.data));
}, false);
</script>
<button onclick="openProxy();">Open remote</button> <br/>
<textarea cols="150" rows="20" id="logger"></textarea>
</body>
</html>
Proxy page at http://example.com/proxy.htm
<!DOCTYPE html>
<html>
<head>
<title>Proxy page</title>
<link rel="stylesheet" href="/css/style.css" />
</head>
<body>
<script>
function toJson(obj) {
return JSON.stringify(obj, null, 2);
}
window.addEventListener('message', function(e) {
console.log('Received message: ' + toJson(e.data));
window.opener.postMessage(e.data, '*');
window.close(self);
}, false);
</script>
<iframe src="http://example.net/remote.htm" frameborder="0" height="300" width="500" marginheight="0" marginwidth="0" scrolling="auto"></iframe>
</body>
</html>
Remote page at http://example.net/remote.htm
<!DOCTYPE html>
<html>
<head>
<title>Remote page</title>
<link rel="stylesheet" href="/css/style.css" />
</head>
<body>
<script>
function remoteSubmit() {
var data = {
message: document.getElementById('msg').value
};
window.parent.postMessage(data, '*');
}
</script>
<h2>Remote page</h2>
<input type="text" id="msg" placeholder="Type a message" /><button onclick="remoteSubmit();">Close</button>
</body>
</html>
== WORKING SOLUTION IN 2020 without iframe ==
Building on answer by tangle, I had success in IE11 [and emulated IE10 mode] using following snippet:
var submitWindow = window.open("/", "processingWindow");
submitWindow.location.href = 'about:blank';
submitWindow.location.href = 'remotePage to communicate with';
Then I was able to communicate using typical postMessage stack, I'm using one global static messenger in my scenario (although I don't suppose it's of any significance, I'm also attaching my messenger class)
var messagingProvider = {
_initialized: false,
_currentHandler: null,
_init: function () {
var self = this;
this._initialized = true;
var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent";
var eventer = window[eventMethod];
var messageEvent = eventMethod == "attachEvent" ? "onmessage" : "message";
eventer(messageEvent, function (e) {
var callback = self._currentHandler;
if (callback != null) {
var key = e.message ? "message" : "data";
var data = e[key];
callback(data);
}
}, false);
},
post: function (target, message) {
target.postMessage(message, '*');
},
setListener: function (callback) {
if (!this._initialized) {
this._init();
}
this._currentHandler = callback;
}
}
No matter how hard I tried, I wasn't able to make things work on IE9 and IE8
My config where it's working:
IE version: 11.0.10240.16590, Update versions: 11.0.25 (KB3100773)
Building upon the answers by LyphTEC and Akrikos, another work-around is to create an <iframe> within a blank popup window, which avoids the need for a separate proxy page, since the blank popup has the same origin as its opener.
Launcher page at http://example.com/launcher.htm
<html>
<head>
<title>postMessage launcher</title>
<script>
function openWnd() {
var w = window.open("", "theWnd", "resizeable,status,width=400,height=300"),
i = w.document.createElement("iframe");
i.src = "http://example.net/remote.htm";
w.document.body.appendChild(i);
w.addEventListener("message", function (e) {
console.log("message from " + e.origin + ": " + e.data);
// Send a message back to the source
e.source.postMessage("reply", e.origin);
});
}
</script>
</head>
<body>
<h2>postMessage launcher</h2>
<p>click me</p>
</body>
</html>
Remote page at http://example.net/remote.htm
<html>
<head>
<title>postMessage remote</title>
<script>
window.addEventListener("message", function (e) {
alert("message from " + e.origin + ": " + e.data);
});
// Send a message to the parent window every 5 seconds
setInterval(function () {
window.parent.postMessage("hello", "*");
}, 5000);
</script>
</head>
<body>
<h2>postMessage remote</h2>
</body>
</html>
I'm not sure how fragile this is, but it is working in IE 11 and Firefox 40.0.3.
Right now, (2014-09-02), Your best bet is to use a proxy frame as noted in the msdn blog post that details a workaround for this issue: https://blogs.msdn.microsoft.com/ieinternals/2009/09/15/html5-implementation-issues-in-ie8-and-later/
Here's the working example: http://www.debugtheweb.com/test/xdm/origin/
You need to set up a proxy frame on your page that has the same origin as the popup. Send information from the popup to the proxy frame using window.opener.frames[0]. Then use postMessage from the proxy frame to the main page.
This solution involves adding the site to Internet Explore's Trusted Sites and not in the Local Intranet sites. I tested this solution in Windows 10/IE 11.0.10240.16384, Windows 10/Microsoft Edge 20.10240.16384.0 and Windows 7 SP1/IE 10.0.9200.17148. The page must not be included in the Intranet Zone.
So open Internet Explorer configuration (Tools > Internet Options > Security > Trusted Sites > Sites), and add the page, here I use * to match all the subdomains. Make sure the page isn't listed in the Local intranet sites (Tools > Internet Options > Security > Local Intranet > Sites > Advanced). Restart your browser and test again.
In Windows 10/Microsoft Edge you will find this configuration in Control Panel > Internet Options.
UPDATE
If this doesn't work you could try resetting all your settings in Tools > Internet Options > Advanced Settings > Reset Internet Explorer settings and then Reset: use it with caution! Then you will need to reboot your system. After that add the sites to the Trusted sites.
See in what zone your page is in File > Properties or using right click.
UPDATE
I am in a corporate intranet and sometimes it works and sometimes it doesn't (automatic configuration? I even started to blame the corporate proxy). In the end I used this solution https://stackoverflow.com/a/36630058/2692914.
This Q is old but this is what easyXDM is for, maybe check it out as a potential fallback when you detect a browser that does not support html5 .postMessage :
https://easyxdm.net/
It uses VBObject wrapper and all types of stuff you'd never want to have to deal with to send cross domain messages between windows or frames where window.postMessage fails for various IE versions (and edge maybe, still not sure 100% on the support Edge has but it seems to also need a workaround for .postMessage)
MessageChannel doesn't work for IE 9-11 between windows/tabs since it relies on postMessage, which is still broken in this scenario. The "best" workaround is to call a function through window.opener (ie. window.opener.somefunction("somedata") ).
Workaround in more detail here

JSON and passing a URL value as a parameter - Chrome Extension

Ok, this is my final tango with this. Below I've listed the code. I'm able to get the value of the url and display it on screen for the current (active tab) in Google Chrome. Now all I have to do is pass that value as a parameter in the URL via JSON. My processing file resides on a our remote server - in php. Everything I've done with respect to this has worked to perfection. However, any attempts to pass the current url or any url as one of the parameters - e.g. ?format=json&url=http://something.com&callback=? - results in nothing. I'm not sure if what I'm doing is wrong or if it is even possible. The important thing to note is that all we are looking to do is pass the url to a remote server for storage, processing etc and send back results. I have everything working but I just can't seem to get the url to pass as a parameter.
<html>
<head>
<title>API JSON Test</title>
<script type="text/javascript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.0/jquery.min.js"></script>
<script>
window.addEventListener("load", windowLoaded, false);
function windowLoaded() {
chrome.tabs.getSelected(null, function(tab) {
document.getElementById('currentLink').innerHTML = tab.url;
});
}
</script>
<script type="text/javascript">
$(document).ready(function(){
var timeService =
"http://api.ulore.com/api2.php?key=abce&url="+tab.url+"&format=json&callback=?";
$.getJSON(timeService, function(data) {
$('#showdata').html("<p>url_results="+data.post.url+"</p>");
});
});
</script>
<div id="showdata"></div>
</head>
<body>
</body>
</html>
Again, all the JSON works fine when I'm testing other code. Even if I put in a NON-URL value as a parameter for url=..... it throws the appropriate error. However, it will not accept a URL for some reason.
Any feedback will be greatly appreciated.
Thanks,
Ethan-Anthony
Try encoding and decoding the url.
http://www.w3schools.com/tags/ref_urlencode.asp
http://php.net/manual/en/function.rawurlencode.php
http://phpjs.org/functions/rawurlencode:501

Scanning URL All the time - Chrome Extension

I need to develop extension, where everytime i write url and in chrome and press enter. My url is first scanned, if it matches some pattern say like if the url patter has youtube in it, redirect it to facebook
This should be done automatically - not everytime i have press the icon of (chrome extension), meaning this script or piece of code will not be running on-click event, rather once installed it will always scan the url entered and do the require change and reload the tab.
Please help me out. I reach this far
<html>
<script>
function getname()
{
chrome.tabs.getSelected( null , function(tab) {
var rawurl="http://www.youtube.com/watch?";
var newurl= "http://www.youtube.com/watch?feature=player_leanback&"
if (0 === tab.url.indexOf(rawurl))
chrome.tabs.update(tab.id, {url: tab.url.replace(rawurl,newurl)});
});
}
</script>
<body onload="getname();">
</body>
</html>
I achieve this but you onload event in J-Script - is there anyway I can do this all the time without using onload() as onload require explicit click all the time.
Rewriting the code
<html>
<script>
function getname()
{
chrome.tabs.getSelected( null , function(tab) {
var rawurl="http://www.youtube.com/watch?";
var newurl= "http://www.youtube.com/watch?feature=player_leanback&"
if (0 === tab.url.indexOf(rawurl))
chrome.tabs.update(tab.id, {url: tab.url.replace(rawurl,newurl)});
});
}
</script>
<body onload="getname();">
</body>
</html>
You should consider APIs such like chrome.webRequest or chrome.webNavigation.
Besides, I believe this extension has implemented everything you mentioned.