Including multiple JavaScript files in Chrome Extension's popup.html - google-chrome-extension

UPDATE:
The problem is caused by including an old version of jQuery(1.4.2).
After I use 1.8.2 instead, the problem is just gone. But I still don't
know why.
I recently made a Chrome extension. Thanks to the post chrome extension insert content script on browser action I realized that I have to include a js file like:
<script src="popup.js"></script>
But later I figure out it seems you cannot include more than one file:
<html>
<head>
<script src="jquery.js"></script> <!-- NOT LOADED -->
<script src="popup.js"></script> <!-- LOADED -->
</head>
<body>
</body>
</html>
What's worse for me is that I cannot access the DOM of the popup HTML in the JS file. Like:
popup.html
<html>
<head>
<script src="popup.js"></script>
</head>
<body>
<a id="intro" href="#" target="_blank">Intro</a>
</body>
</html>
popup.js
/*
... jQuery Codes here ...
jquery.js cannot be included via src="jquery.js"
but by copy and paste its source code here it works
*/
$("#intro").click(function(){
alert("clicked"); // Not fireing at all
});
I am wondering what I can do to fix this. Thanks very much!

Here is a basic example of what you could use to get it working. My best guess is that it only appeared that jQuery wasn't loading because of how your popup.js is set up (it is trying to attach the click functionality before the element has loaded). I'm no JS expert, so I'm sure others will have better ideas of how to wait for the DOM to load, but this works as a basic test (NOTE: this uses a local version of the latest version of jQuery (1.8.2 currently), as the new content policies in manifest 2 do not allow in-line scripts):
Manifest.json
{
"name": "Test Extension",
"version": "1.0",
"manifest_version": 2,
"description": "Testing",
"browser_action": {
"default_icon": "my_icon.png",
"default_title": "My Text Extension",
"default_popup": "popup.html"
},
"permissions": [
"tabs", "http://*/", "https://*/"
]
}
Popup.html
<html>
<head>
<script type="text/javascript" src="jquery.min.js"></script>
<script type="text/javascript" src="popup.js"></script>
</head>
<body>
<a id="intro" href="#" target="_blank">Intro</a>
</body>
</html>
Popup.js
/*
Here we wait for the body of the popup to load before
attaching our functionality
*/
window.onload = function() {
$("#intro").click(function(){
alert("clicked"); // Should fire now
});
};

The reason this is happening, is because the page is being loaded in order, and the scripts are firing before the DOM is loaded. This means that the scripts are called before the DOM even exists, so it cannot see the DOM at all; it's loading after the script.
Using events to wait for the DOM is one method to get around this, but you can also add the scripts at the end or after the body tag to be loaded last, so that the DOM is loaded first. There are of course many people who will argue this is bad practice, as well as vice versa. The reason being that you may have scripts load while the DOM loads, or because there are many large scripts that cause a lag in the loading, and these are all valid points when discussing jQuery manipulated websites.
The opposing practice can be beneficial when working with Chrome Extensions. One reason is to always give some representational responsiveness, even with the most intensive extensions, as well as not having to worry about waiting for the DOM in the code. Really it depends on what you need, but it's always beneficial to know all of your options. You can see both practices used in the Sample Chrome Extensions.
With jQuery you may want to use the Ready method instead, as onload waits until everything on the page is loaded (images, video, links, scripts, etc). Unlike onload, the ready method is called when the DOM itself is done loading, regardless of the page actually being done loading. You can do this with:
$(document).ready(function() {
// jQuery code to execute after
});
You can also wait for the DOM in JavaScript using the DOMContentLoaded event:
document.addEventListener('DOMContentLoaded', function() {
// JavaScript code here
});

Related

Chrome extension passing data from background.js to new tab

In my chrome extension I want to show a page with some of the usager's usage statistics. I have been trying to go about this by creating a new tab from the background.js to display an HTML page:
chrome.tabs.create({
url: '/results.html',
active: true
});
where results.html looks like this:
<!DOCTYPE html>
<html lang='en'>
<head>
<script src='js/charts.js'></script>
</head>
<body>
<canvas id='myChart' style='height:400px; max-width:800px; background-color:red;'></canvas>
</body>
<script src='js/results.js'></script>
</html>
The problem is that I then need to pass the actual usage data from the background.js page to this new results.html page. The only thing I can think of is to add another content script that attaches to the results.html page.
"content_scripts": [
{
"matches": [
"*://*.results.html"
],
"js": ["js/results_content.js"],
"run_at": "document_idle"
}
]
This doesn't seem to work, otherwise, I could then have the background page send the data through the results_content.js script and display the charts.
The only other idea I can think of is to just open a new tab to obscurewebsite.com and have a content script that does something like document.body.innerHTML = "" and rebuild my page using only javascript. I don't love this solution.
Is there a way to pass information through the chrome.tabs reference? Or another way to pass the data? Any help is appreciated.

iframe-resizer js library: moveToAnchor from parent page

How can I scroll to a certain anchor tag inside the IFrame page?
Using the ingenious Iframe-Resizier Library by David J. Bradshaw
https://github.com/davidjbradshaw/iframe-resizer
I’m including an IFrame with a lot of content (=long page) inside the outer page. So if I link to the page, then much of the content isn't visible on the first screen and under certain circumstances I would like to jump to a specific anchor tag further down in the iframe.
<html>
<a href=“outer-page.html#somewhere_name” />
</html>
seems not to work
I am using "inPageLinks: true" like this:
<script type="text/javascript">
iFrameResize({
heightCalculationMethod: 'lowestElement',
inPageLinks: true
</script>
My question now is: How can I make the outer page scroll down to a certain anchor tag without the need to implement something new inside the iframe page? The anchor tag in this case is located inside the IFrame page.
When I include the IFrame page like
<html>
<iframe id=“strytl” src=“iframe-page.html#somewhere_name”></iframe
</html>
Then the (re)sizing of the IFrame seems not to work perfectly and contents at the top of the iframe are getting cut off.
But with moveToAnchor it works perfectly from inside the IFrame and the page is magically scrolling down to the anchor tag. So in the iframe page I can call:
<script type="text/javascript>
parentIFrame.moveToAnchor('somewhere_name’);
</script>
But how can I trigger this from the parent page?
<script type="text/javascript>
$('iframe#strytl').iFrameResize({moveToAnchor: 'somwhere_name'});
</script>
results in this error:
<script type=“text/javascript”>
[iFrameSizer][Host page: strytl] Ignored iFrame, already setup.and
</script>
And
<script type="text/javascript">
iFrameResize({
heightCalculationMethod: 'lowestElement',
inPageLinks: true,
moveToAnchor: 'somewhere_name'});
</script>
seems to have no effect at all.
(In this case the outer page and the iframe have different server names.)
<script type=“text/javascript”>
var myFrm = document.getElementById('strytl');
var myCw = myFrm.contentWindow;
myCw.parentIFrame.moveToAnchor(‘somewhere_name’);
</script>
result:
<script type=“text/javascript”>
Error: Permission denied to access property “parentIFrame"
</script>
Can I jump to an anchor in the iframe from the outer page at all?
Something like this.
<script type="text/javascript">
iFrameResize({
heightCalculationMethod : 'lowestElement',
inPageLinks : true,
initCallback : function (iFrame){
iFrame.iFrameResizer.moveToAnchor('someAnchor');
}
});
</script>

why does mathjax go throught the same processing on same visited page each time?

I have a page with mathml to be processed by mathjax. I noticed each time I visit the page (not just the first time) I see the same processing:
...waiting for cdf.mathjax.org
...processing math...
...typesetting math 5% 10% 20%....
I would have expected that once the page is loaded first time, then next time it is visited, it will come up instantly since it is in the browser cache now. But I guess my understanding was wrong.
The header of the page is
<!DOCTYPE html>
<html>
<head><title>integrals 51 - 100</title>
<meta charset="UTF-8" />
<meta name="generator" content="TeX4ht (http://www.cse.ohio-state.edu/~gurari/TeX4ht/)" />
<link rel="stylesheet" type="text/css" href="report.css" />
<script type="text/x-mathjax-config"> MathJax.Hub.Config({ extensions: ["tex2jax.js"], jax:
["input/TeX", "output/HTML-CSS"], tex2jax: { inlineMath: [ ['$','$'], ["\\(","\\)"] ],
displayMath: [ ['$$','$$'], ["\\[","\\]"] ], processEscapes: true },
"HTML-CSS": { availableFonts: ["TeX"] } }); </script> <script type="text/javascript"
src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML">
</script><style type="text/css"> .MathJax_MathML {text-indent: 0;}
</style></head>
<body>
My question is: Is this how it is supposed to work? I am not forcing the page to reload by something like holding the SHIFT key and reloading the page. I simply visit the page, hit the browser back key, then click on the link again to visit the page again.
I tried this on firefox 34.0.05 and Chrom. I am on windows 7.
Well mathjax formatted equations are generated by javascript. Each time a page is reloaded the javascript is rerun. To prevent this javascript being run each time you would need some sort of cached solution requiring complex code in the backend. There are problems with caching the results as not all browser are the same, the font size may be different and the actual window sizes can vary. All these can impact on the precise details of the equations generated.
People have been working on a cached mathjax solution on wikipedia but the results are still inferior to those generated on the fly.

Page action to open new page

Can I use a page action to directly open a new page? I have a link in my popup.html, but it would be better to have the page open when they click the icon so that they would only need one click instead of two.
<!doctype html>
<html>
<head>
<title>Popup</title>
<link href="popup.css" rel="stylesheet" type="text/css">
</head>
<body>
click here
</body>
</html>
Yes, a way to achieve this would be as follows:
chrome.pageAction.onClicked.addListener(function(tab){
chrome.tabs.create({url: "http://www.domain.com/details.html", "active":true});
});
See Chrome Page Action | onClicked
Note that you will need to declare the tabs permission in your manifest file:
"permissions": ["tabs",...],
I don't think there is any elegant way to handle both the situations on page action click:
Open popup
Open a new page
If you always want to open a new tab with some URL whenever page action is clicked, just remove the popup. And use the code just like #Flo has mentioned.
chrome.pageAction.onClicked.addListener(function(tab) {
chrome.tabs.create({url: "http://www.example.com", "active":true});
});
PS: To remove the popup, there are two options:
Remove the popup from manifest.json
Pragmatically like chrome.pageAction.setPopup('')

meteor real router for multi page apps without JavaScript render

I am new to meteor and I am trying to do multi-page application where http://www.mydomain.com/page1 will result a totally different page from http://www.mydomain.com/page2.
By totally different I mean that I don't want the page to be rendered by the client.
I tried to use meteor-router but What I got is something like:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="/myapp.css?9297ad4aa173c4e0c19aebd27c62a5c43242bb93">
<script type="text/javascript">
__meteor_runtime_config__ = {"ROOT_URL":"http://localhost:3000","serverId":"iMp4kgzzeqDtktJoY"};
</script>
<script type="text/javascript" src="/packages/underscore/underscore.js?6d71e6711255f43c0de8090f2c8b9f60534a699b"></script>
<script type="text/javascript" src="/packages/meteor/client_environment.js?07a7cfbe7a2389cf9855c7db833f12202a656c6b"></script>
<script type="text/javascript" src="/packages/meteor/helpers.js?2968aa157e0a16667da224b8aa48edb17fbccf7c"></script>
...
...MANY MANY MANY SCRIPTS.... ?!?
...
...
<script type="text/javascript" src="/myapp.js?2866dcdb5c828b129cdd3b2498a4bf65da9ea43f"></script>
<title>myapp</title>
</head>
<body>
</body>
</html>
And this is not what I want. I want page1 route will return me:
<!DOCTYPE html>
<html>
<head>
My meta tags
</head>
<body>
page1
</body>
</html>
And I want page2 to return different meta tags with different content.
In order to be clear, lets assume that my clients sometime doesn't have javascript. I don't asking about whether meteor is the right framework! I am asking only if can I do this with meteor.
Meteor works a bit different compared to the traditional LAMP stack. Basically it works by patching out the DOM to only where the changes are needed as opposed to re-downloading the whole web page. It makes for a very satisfying end user experience on modern web browsers.
To use meteor router you need to find a spot that you want to patch out with new data for different pages with {{renderPage}}. You can use something like
<head>
<title>xx</title>
</head>
<body>
{{renderPage}}
</body>
<template name="page1">
<h2>Hello!</h2>
</template>
<template name="page2">
<h2>Ola!</h2>
</template>
Now you need to define a router in your client side javascript:
Meteor.Router.add({
'/page1': 'page1',
'/page2': 'page2'
});
So if you load /page1 you would see Hello! and if you load /page2 you would see Ola! as defined in the <template name="page2">..</template>
With the meta tags you need to use javascript to create them. With something like
$('head').append("<meta...");
Again this depends on your preference, personally I find these type of apps load ridiculously fast between web pages as compared to other 'thin' based websites. (Have a look at meteor.com to see how fast you can swap between the pages). The browser does need javascript, however.
Of note is in production mode there will only be 1 script tag.

Resources