How can I use angular inside a Chrome extension content script - javascript

I've been working on a Chrome extension using angular. I've built off a simple example that uses the browser action popup (popup.html) to host all of my angular code.
On that page, I load all the angular scripts and attach the angular routing:
<script src="bower_components/jquery/dist/jquery.js"></script>
<script src="bower_components/bootstrap/dist/js/bootstrap.js"></script>
<script src="bower_components/angular/angular.js"></script>
<script src="bower_components/angular-route/angular-route.js"></script>
<script src="bower_components/angular-bootstrap/ui-bootstrap-tpls.js"></script>
<script src="scripts/shared/google_auth.js"></script>
<script src="scripts/shared/util.js"></script>
<script src="scripts/app.module.js"></script>
<script src="scripts/app.config.js"></script>
<script src="scripts/filepicker/filepicker.module.js"></script>
<script src="scripts/filepicker/filepicker.controller.js"></script>
<script src="scripts/filepicker/filepicker.factory.js"></script>
<script src="scripts/filepicker/filepicker.components.js"></script>
<script src="scripts/filepicker/filepicker.filecreator.js"></script>
<script src="scripts/notetaker/notetaker.module.js"></script>
<script src="scripts/notetaker/notetaker.controller.js"></script>
<script src="scripts/notetaker/notetaker.factory.js"></script>
<script src="scripts/notetaker/notetaker.component.js"></script>
My app.config.js has the routing setup:
angular.
module('researchBuddyApp').
config(['$locationProvider', '$routeProvider',
function config($locationProvider, $routeProvider) {
$locationProvider.hashPrefix('!');
$routeProvider.
when('/filepicker', {
template: '<filepicker></filepicker>'
}).
when('/notetaker', {
template: '<notetaker></notetaker>'
}).
otherwise('/notetaker');
}
]);
So far I've been mostly writing and testing functionality; now it's time to start to actually start integrating this into the pages where my content is. The plan for the app is to be able to take notes from webpages, so the context menu needs to be able to launch a form.
I've figured out how to setup event handlers for context menus and I've also figured out how to use content scripts and inject code into webpages. But, Chrome blocks access to the local pages of extensions unless explicitly allowed. So there are three solutions that I can see moving forward with, and I am not sure the arguments in favor of each practice.
I could just use my context menu to launch a new chrome window to the appropriate route off of popup.html.
I can add popup.html to "web_accessible_resources" in the manifest file, which will give the content script access to render any part of my angular app inside an iframe.
I can rework how I load my app as demonstrated by angularjs templates in chrome extension so it's loaded throught the manifest.json file and then bootstrapped within the content script itself.
I don't have any idea which of these might be a better approach, and I don't have a great need to actually use the browser_action popup itself.

Related

Angular UI Router: ui-sref does not render render the page I'm trying to route to, but it appears in my dev tools

I've been banging my head against the problem for embarrassingly long now. I'm using Angular UI Router to handling the routing in a small personal project I'm working on, and I have a strange issue. I have a VERY simple HTML file:
<head>
<title>MY FUN EXCITING PROJECT</title>
<script src='node_modules/angular/angular.min.js'></script>
<script src='node_modules/angular-ui-router/release/angular-ui-router.min.js'></script>
<script src='app.js'></script>
<script src='routes.js'></script>
<script src='dist/auth/authenticationController.js'></script>
<script src='dist/auth/authenticationFactory.js'></script>
</head>
<body>
<H1>I AM A FILE. HELLO.</H1>
<a ui-sref='login'>CLICK ME</a>
</body>
And, again, a VERY simple route provider file:
(function () {
'use strict';
angular.module('project',['ui.router'])
.config(['$stateProvider', function ($stateProvider) {
$stateProvider
.state('login', {
url: '/login',
templateUrl:'dist/auth/authentication.html'
});
}])
})();
And the authentication.html file is literally just a I AM AN AUTHENTICATION PAGE right now.
What's happening is that clicking on the link will cause the address in the address bar to change properly, but the template itself won't render. If I look in the dev tools, though, the page is being sent back from the response (screenshot attached).
I'm using a basic barebones node server to run the server for this, and using
app.use(express.static(__dirname+'/public'));
to serve all the files. Is there something basic I'm missing? I'd infinitely appreciate any help. Thank you!

local absolute paths (C:...) for script tag

Is there any way to properly reference a javascript file on disk that is not necessarily relative to the HTML file itself but to the file system of the host?
I am currently working on a strictly local site (always opened with file:// ...) and no web server. (only windows hosts)
This works for chrome and firefox without any issues:
<script src="resources/test1.js" type="text/javascript"></script>
<script src="resources/test2.js" type="text/javascript"></script>
<script src="file:///C:/test3.js" type="text/javascript"></script>
<script src="file://localhost/C:/test4.js" type="text/javascript"></script>
<script src="//localhost/C:/test5.js" type="text/javascript"></script>
Only works in chrome:
<script src="file:C:/test6.js" type="text/javascript"></script>
<script src="C:/test7.js" type="text/javascript"></script>
<script src="C:\test8.js" type="text/javascript"></script>
The Internet Explorer (IE11) on the other hand does not load these files (test3.js - test8.js) without any warning or error. Is there a proper way to do that?
I also tried adding a shared folder (//localhost/data/test.js) to ensure i don't need any : for the url. Did work for firefox and chrome, but not for IE.
I am aware that this is not the intended use of script tags or even HTML sites and that 'proper' is probably not the correct term anyway.
You can remove the alert by allowing 'active content' option. Go to Tools ->Internet options ->Advanced -> Security ->Allow active content to run files
Hope this helps!

ng-view won't display template

I have been working a bit with Angular and I tried to implement simple routing.
I have a basic HTML which contains reference to all the required scripts and a ng-view tag.
For some reason, when the page is loaded, the template isn't shown in the ng-view location. Why isn't it shown, and how to fix it?
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.4/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.4/angular-route.js"></script>
<script src="routCtrl.js"></script>
</head>
<body ng-app='ngRouteTest'>
<div ng-view></div>
</body>
and the the script file:
var ngRouteTest = angular.module('ngRouteTest',['ngRoute']);
ngRouteTest.config(function($routeProvider){
$routeProvider
.when('/',
{templateUrl : '/routView1.html'})
});
You need to redirect to that page so that routing will come to know which page to render inside ng-view directive.
There are multiple ways to do it.
Define one more otherwise to redirect to /.
$routeProvider.otherwise({redirectTo: '/'})
Add anchor to page that will redirect to /.
<body ng-app='ngRouteTest'>
Home Page
<div ng-view></div>
</body>
Having default url on page in <head> tag.
<base href="/"/>
Okay first you need to run your code from a server, so to test it locally use http-server which is really easy to prepare.
Then you will need to change your templateUrl path from:
{templateUrl : '/routView1.html'}
to:
{templateUrl : './routView1.html'}
After starting a local host and ruining the code from there it worked perfectly fine.
The issue was with the chrome related security when you make local ajax calls.
So one has this problem should do one of the following things:
1.Disable web-security in chrome.
2.Start a local host to test.

Why AngularJS routes are not working in local?

I have html file which implements AngularJS routes as follows,
index.html:
<!DOCTYPE html>
<html ng-app="demo">
<head>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div ng-view>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.min.js"></script>
<script src="http://code.angularjs.org/1.2.1/angular-route.min.js"></script>
<script>
// Code goes here
var demo = angular.module('demo', ['ngRoute']);
demo.config(function($routeProvider){
$routeProvider.when('/', {
controller: 'testController',
templateUrl: 'test.html'
})
})
var controllers = {};
controllers.testController = function($scope){
$scope.first = "Info";
$scope.customers=[
{name:'jerry',city:'chicago'},
{name:'tom',city:'houston'},
{name:'enslo',city:'taipei'}
];
}
demo.controller(controllers)
</script>
</body>
</html>
test.html:
<div>
<input type="text" ng-model="name"/>
</br>
{{first}}
</br>
<ul>
<li ng-repeat="cust in customers | filter:name">{{cust.name | uppercase}} - {{cust.city}}</li>
</ul>
</div>
You can find the working version here
But why is it not working when I run the same in my local browser :(
Here is the chrome console error:
Any help appreciated! :)
It is important to make it clear. For security reasons, Chrome (for example) won't allow you to load local files (ie: the templates for your views). My suggestion is to set up a web server to test your applications:
Use the free edition of the Visual Studio Express for web development.
Use gruntjs to quickly set up your project.
Alternatively you can use inline templates in place of loading it externally, but it does not seems to be a good practice.
Edit:
Using the console error print that you posted, Chrome is blocking your ajax request. You can bypass this restriction using a command line argument:
chrome.exe --allow-file-access-from-files
However I would encourage you to set up a simple local web server, It will prevent you for some headaches while your are learning...
You can use Firefox for test. Route and ajax will work.
But it is better to set up a web server like #gustavodidomenico said
the work around to make ng-view work in local is to put the content of other htmls in the script tag as
<script type="text/ng-template" id="index22.html">
This is index 2 template.
</script>
<script type="text/ng-template" id="index33.html">
This is index 3 template.
</script>
in the same HTML from where the call is being made.
ngview makes an AJAX call to load the content of external HTMLs or seperate HTMLs , chrome does not allow AJAX call for local resources , IE 11 also shows 'Access is denied' error message.
when including in script tags , this AJAX call is not made.
There is a Chrome Extension called Web Server for Chrome. you can add it and then lunch it, in browse dialog choose your working folder, then it gives you a Local URL, you can test your app there.

Meteor JS: use external script

There are some services (like FB like or AddThis) that provide a snippet of code.
It looks like
<div class="service-name" data-something="x"></div>
<script type="text/javascript" src="http://example.com/service-name.js"></script>
OK, cool, so normally you paste it to your HTML and it works. Not with Meteor.
Here's what I see:
<script> inside of template / body is not loading -- I don't see it in Resources, something in Meteor is actually preventing browser from recognizing it as a JS file
it works from <head>
Now here are the problems and questions:
I don't want loading it from <head> -- because of the speed
Even if I load it from there -- we have QA and PROD environments. They must load this script from different domains (like service-domain-qa.example vs. example.com)
And surprisingly you cannot use template helpers / variables in the <head>.
With traditional frameworks it's not a question at all - you can include scripts anywhere and they just load; you can use logic / variables in any part of you server templates.
So, how should I do this in Meteor?
Let me repeat:
I need some external scripts (hosted on 3rd party domain) to be loaded into my app page
Saving this script into my project's folder is not an option
Script path depends on the environment (we already have the settings system), so the place of the template that renders it should be passed some data from the code
I know the way to achieve this with dynamic script loading from my code (with LAB.js or whatever) on Template.created, but this is so much an overkill...
<script> tags in body or templates aren't executed by Meteor, they are parsed and then handled by Meteor's templating system. You can't expect a script tag in either of those to just work as it would with a normal HTML page.
The solution is to use Template events (where you could manually append the script tag to the body or something) or load it dynamically like you said. It's not overkill, it's how Meteor works - remember, there is no traditional HTML page or body, there's just the Meteor API, and the Meteor API specifies that in order to load and execute external scripts, you must use the appropriate API methods.
My solution is use packages. See https://github.com/meteor/meteor/tree/master/packages/spiderable for more details.
Package.describe({
summary: "External script"
});
Package.on_use(function (api) {
api.use(['templating'], 'client');
api.add_files('external_script.html', 'client');
});
<head><script type="text/javascript" src=""//mc.yandex.ru/metrika/watch.js""></script></head>
If you are using IronRouter you can load external scipt using this package:
https://github.com/DerMambo/wait-on-lib
Router.map( function () {
this.route('codeEditor',{
waitOn: IRLibLoader.load('https://some-external.com/javascript.js')
});
});
Why not use jQuery's getscript?
http://api.jquery.com/jquery.getscript/
You can add a callback function
You could use something like yepnope to load the script asynchronously. I use this to load leaflet as and when I need. I'm starting to move over to loading more scripts via yepnope, so that my application renders the bare minimum on initial page load. I place the yepnope stuff inside Template.created.
Using iframe and the public directory was a hack I used to get script code embedded. In this it was for google adwords code and I did this my main html template:
<iframe src="/gads.html?v={{{unique}}}" seamless width="160" height="600"
scrolling="no" frameborder="0" marginheight="0" marginwidth="0"
style="margin:0;padding:0;border:none;width:160px;height:600px"></iframe>
and then in the public directory put an gads.html file with my google adwords code, like this:
<html>
<head>
<style type="text/css">
* {
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<div>
<script type="text/javascript"><!--
google_ad_client = "ca-pub-54*********";
google_ad_slot = "66******";
google_ad_width = 160;
google_ad_height = 600;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>
</body>
</html>
that worked to get the code on the page, although it's far from ideal (for one thing, I think it violates google's terms of service).
I'm using METEOR 1.0. I have put all external SCRIPT tags inside a DIV element right before the tag in the layout template. Meteor recognizes them without any issue and they are loaded by browser.

Categories