Chrome Extension: Using addEventListener() - google-chrome-extension

In the tutorial for migrating a Google Chrome Extension to Manifest Version 2, I am directed to Remove inline event handlers (like onclick, etc) from the HTML code, move them into an external JS file and use addEventListener() instead.
OK, I currently have a background.html page that looks like this…
<html>
<script type="text/javascript">
// Lots of script code here, snipped
…
</script>
<body onload="checkInMyNPAPIPlugin('pluginId');">
<object type="application/x-mynpapiplugin" id="pluginId">
</body>
</html>
Following another directive, I've moved that Lots of script code into a separate .js file, and following this directive, I need to remove the onload= from the body tag, and instead cal addEventListener() in my script code. I've tried several approaches, but am apparently guessing wrong. What will that code look like? In particular, upon what object do I invoke addEventListener()?
Thanks!

I normally use this for body onload event...
document.addEventListener('DOMContentLoaded', function () {
// My code here.. ( Your code here )
});
For somethings it is working.. but really, I think we should use..
window.addEventListener('load', function () {
document.getElementById("#Our_DOM_Element").addEventListener('change - or - click..', function(){
// code..
});
});

Related

Add custom view to jhipster app

I would like to add a custom view to jhipster app on index.html
I already created the link in navbar.html and added the html file on path src/main/webapp/scripts/app/custom/newView.html
<a ui-sref="newView" data-toggle="collapse" data-target=".navbar-collapse.in">
<span class="glyphicon"></span>
<span class="hidden-sm">new view</span>
</a>
When I click on the link it doesn't work. Probably it needs a custom route in angular but I can't figure out how to create it. What else should I do?
In addition to the other answer, here is another piece of information. Maybe somebody else will find it useful. I had a similar problem with a custom view but only in production. Everything was fine in dev mode. In production mode, nothing would display and I had this javascript error that read "could not resolve ... from state ...".
It turns out that my javascript file (where the state was declared) was declared like this in index.html
<!-- build:js({.tmp,src/main/webapp}) scripts/app.js -->
<script src="scripts/app/app.js"></script>
<script src="scripts/app/app.constants.js"></script>
...
<!-- endbuild -->
<!-- custom -->
<script src="scripts/app/pages/quizz/quizz.js"></script>
<script src="scripts/app/pages/quizz/quizz.controller.js"></script>
I had created the separation on purpose, just to make it easier to read. Once I moved it up to have it before endbuild, the problem disappeared. I guess this is related to how the app is packaged somehow? I haven't looked at how it does it.
I've figured it out:
I had to add a angularjs route. Created a js file
src/main/webapp/scripts/app/custom/newv.js with the following content:
angular.module('jCrudApp')
.config(function ($stateProvider) {
$stateProvider
.state('newView', {
parent: 'site',
url: '/newView',
views: {
'content#': {
templateUrl: 'scripts/app/custom/newView.html',
//controller: 'MainController'
}
}
});
});
and import the new script in index.html
<script src="scripts/app/custom/newv.js"></script>

Behavior when async: false and true

I am using AMD way of coding and when I make async:false I don't see any difference in execution behavior i.e. making async true or false I see no difference.
Please have a look at code snippet below:
<html>
<script type="text/javascript" src="../../dojoroot/dojo/dojo.js" data-dojo-config="async:true, parseOnLoad:true"></script>
<script type="text/javascript">
require(["dojo/domReady!"], function(){
alert("I am inside DOM ready");
});
require(["dojo/ready"], function(ready){
ready(function(){
alert("I am inside ready");
});
});
</script>
<body>
some div's here
</body>
</html>
OUTPUT:
In both the case i see first "I am inside DOM ready" and then "I am inside ready" alert next.
Could you please explain what is the difference if I add async : true and async:false?
Thanks.
To answer your question, if async is set to a truthy value (true, 1, etc.), dojo/domReady and dojo/ready will be loaded when require is called. If async is not set, these modules are loaded immediately when dojo.js is loaded. So there is no impact on how your code executes, it’s just about when those modules become available for use.
This is snippet from Dojo AMD description:
For backwards-compatibility, the loader starts up in synchronous mode by default, which loads the Dojo base API automatically:
<script src="path/to/dojo/dojo.js"></script>
<script>
// the dojo base API is available here
</script>
To put the loader in the AMD mode, set the async configuration variable to truthy:
<script data-dojo-config="async: 1" src="path/to/dojo/dojo.js"></script>
<script>
// ATTENTION: nothing but the AMD API is available here
</script>
Note that you can only set the async flag before dojo.js is loaded, and that in AMD mode, neither Dojo Base nor any other library is automatically loaded - it is entirely up to the application to decide which modules/libraries to load.

YUI error: Uncaught ReferenceError: YUI is not defined

I am a jQuery user and just learning YUI. I have the following code and I keep the error that YUI is not defined. I know it is an issue with linking to the library but I'm not exactly sure what. I had someone else test my code where they had YUI held locally and it worked fine. If I need to do this, how do I obtain a copy of the min.js file? When you download a copy from the YUI site its a tonne of files...
<head>
<title>YUI3 Test</title
<script src="http://yui.yahooapis.com/3.2.0/build/yui/yui-min.js"></script>
</head>
<body>
<div id="menu">
<p>Click here to test.</p>
</div>
<script>
YUI().use('node', 'event', function (Y){
var changeText = function(e){
e.target.setHTML("<p>Now you see the test working.</p>");
}
var node = Y.one("#menu");
node.on("click", changeText);
//node.on("click", function(e){
// Y.one(node).load('menu.html');
//});
});
</script>
</body>
Thanks!
You're missing a > after </title. This may be causing the script tag not to be recognized and so it's not loading.
Here it is broken: http://jsbin.com/ubaxoy/1/edit
And here it works after adding the missing >: http://jsbin.com/ubaxoy/2/edit
I also had to change setHTML to setContent because YUI 3.2 didn't have setHTML yet. I'd also recommend you to use a newer version of YUI, from 3.9.1 up. There have been a number of great additions since 3.2.

MathJax with RequireJS, how to set config

Usually, I can include MathJax in a script tag like:
<script src="path-to-MathJax/MathJax.js?config=default"></script>
But with RequireJS, I can include the config, but what happens to the config?
It's now explained in the Mathjax documentation :
https://github.com/mathjax/MathJax-docs/wiki/Integrating-mathjax-into-x%3A-require.js
The requirejs documentation on github mentions that you can gain fine-grained control on the URL, by overriding the requirejs load function:
https://github.com/jrburke/requirejs/wiki/Fine-grained-URL-control
<script src="require.js"></script>
<script>
(function () {
var load = requirejs.load;
requirejs.load = function (context, moduleId, url) {
//modify url here, then call original load
return load(context, moduleId, url);
};
//Now load code.
require(['main']);
}());
</script>
Not ideal as you would loose the ability to load it only when required. If nothing else works, you can always use this approach as last resort.
Instead of loading MathJax from within require, load it as a script.
Instead of:
<script data-main="main" src="libs/require.js"></script>
Try this:
<script src="libs/require.js"></script>
<script src="path-to-MathJax/MathJax.js?config=default"></script>
<script>require(["main"]);</script>
You could also load require.js and do
<script>require(["path-to-MathJax/MathJax.js?config=default"]);</script>

Chrome inline installation works only half of the time

we've set up a simple inline webstore installer for our app.
The app site has been verified. The inline installation does work correctly for half of us inside our company, but it doesn't work for the other half. They would get "Uncaught TypeError: Cannot call method 'install' of undefined testsupport.html:15
Uncaught SyntaxError: Unexpected token ). It's as though the chrome or chrome.web variable isn't initialized.
Why does the inline installation work only on some machines but not on others? All these machines have the same chrome browser version.
TIA
I've not seen this issue before but I will try to provide a breakdown of the setup I use to manage inline installations for the multiple Chrome extensions on my website.
Within the head node of every page (optionally, only pages that may include one or more Install links) I add the required links to each extension/app page on the Chrome Web Store. This allows me to easily add install links anywhere on the page for various extensions/apps. The JavaScript simply binds an event handler to each of the install links once the DOM has finished loading. This event handler's sole purpose is to install the extension/app that it links to when clicked and then to change its state to prevent further install attempts.
<!DOCTYPE html>
<html>
<head>
...
<!-- Link for each extension/app page -->
<link rel="chrome-webstore-item" href="https://chrome.google.com/webstore/detail/dcjnfaoifoefmnbhhlbppaebgnccfddf">
<script>
// Ensure that the DOM has fully loaded
document.addEventListener('DOMContentLoaded', function() {
// Support other browsers
var chrome = window.chrome || {};
if (chrome.app && chrome.webstore) {
// Fetch all install links
var links = document.querySelectorAll('.js-chrome-install');
// Create "click" event listener
var onClick = function(e) {
var that = this;
// Attempt to install the extension/app
chrome.webstore.install(that.href, function() {
// Change the state of the button
that.innerHTML = 'Installed';
that.classList.remove('js-chrome-install');
// Prevent any further clicks from attempting an install
that.removeEventListener('click', onClick);
});
// Prevent the opening of the Web Store page
e.preventDefault();
};
// Bind "click" event listener to links
for (var i = 0; i < links.length; i++) {
links[i].addEventListener('click', onClick);
}
}
});
</script>
...
</head>
<body>
...
<!-- Allow inline installation links to be easily identified -->
Install
...
</body>
</html>
In order for this system to work fully you also need to support scenarios where the user has returned to your website after installing your extension/app. Although the official documentation suggests using chrome.app.isInstalled this doesn't work when multiple extensions/apps can be installed from a single page. To get around this issue you can simply add a content script to your extension/app like the following install.js file;
// Fetch all install links for this extension/app running
var links = document.querySelectorAll('.js-chrome-install[href$=dcjnfaoifoefmnbhhlbppaebgnccfddf]');
// Change the state of all links
for (var i = 0; i < links.length; i++) {
links[i].innerHTML = 'Installed';
// Website script will no longer bind "click" event listener as this will be executed first
links[i].classList.remove('js-chrome-install');
}
Then you just need to modify your manifest.json file to ensure this content script is executed on your domain.
{
...
"content_scripts": [
{
"js": ["install.js"],
"matches": ["*://*.yourdomain.com/*"],
"run_at": "document_end"
}
]
...
}
This will result in the content script being run before the JavaScript on your website so there will be no install links with the js-chrome-install class by the time it is executed, thus no event handlers will be bound etc.
Below is an example of how I use this system;
Homepage: http://neocotic.com
Project Homepage: http://neocotic.com/template
Project Source Code: https://github.com/neocotic/template
Your inline installation markup is:
<a href="#" onclick="chrome.webstore.install()">
CaptureToCloud Chrome Extension Installation
</a>
(per one of the comments, it used javascript:void(0) before, which is equivalent to # in this case).
Your <a> tag both navigates the page and has an onclick handler. In some cases, the navigation takes place before the onclick handler finishes running, which disturbs the code that supports inline installation.
If you switch to using a plain <span> (styled to look like a like, if you'd like), then you should no longer have this problem:
<span onclick="chrome.webstore.install()" style="text-decoration: underline; color:blue">
CaptureToCloud Chrome Extension Installation
</span>
Alternatively, you can return false from your onclick handler to prevent the navigation:
<a href="#" onclick="chrome.webstore.install(); return false;">
CaptureToCloud Chrome Extension Installation
</a>
(though since you're not actually linking anywhere, there isn't much point in using the <a> tag)
I get the error you mentioned AND a popup window that allows me to install the extension. So probably everybody get the error but for some it is preventing installation.
I got rid of the error by replacing javascript:void() by # in href.
CaptureToCloud Chrome Extension Installation

Resources