How to using Snap.svg and Snap.js via angular-snap together? - angularjs

I try to use two dependencies:
"snap.svg": "~0.2.0", # snapsvg.io
"angular-snap": "~1.4.1", # jtrussell.github.io/angular-snap.js/
How I guess, it seems angular-snap uses a global Snap object as snap.svg and overrides the Snap object of Snap.svg.
In this order the Snap.svg functionalty goes away. If I revert the order of import, some Snap.js functionalty is missed.
Watch this plunkr http://plnkr.co/edit/rE4pNDqQnBh2e5wtqGUO?p=preview and swap the includes.
How can I use both libs?
Thx ahead!

I think your best bet is going to be using a module loader like RequireJS to pull both Snap.js and Snap.svg into you application in a controlled way, it looks like both support AMD module loaders.
Unfortunately this will mean you won't be able to rely on the snap-content directive from Angular Snap anymore. You'll need to create a new Snap.js snapper instance yourself and make use of snapRemote#register.
Here's some pseudo code:
require(['jakiestfu/Snap.js/snap'], function(SnapJS) {
snapRemote.register(new SnapJS(snapOptions));
});
require(['adobe-webplatform/Snap.svg/snap.svg'], function(SnapSVG) {
// Do stuff with SnapSVG...
});
Also, you'll want to assign a "snap-content" class name to the element you initialize your snapper with (this is also usually handled by the snap-content directive).
Edit:
I'm not recommending this approach but it should work as well if you don't mind some hacks:
In your head:
<script src="//cdn.jsdelivr.net/snap.svg/0.2.0/snap.svg.js" type="text/javascript"</script>
<script>
// Save Snap.svg before it gets clobbered!
window.SnapSVG = Snap;
</script>
<script src="snap.js" type="text/javascript" charset="utf-8"></script>
After that you could go on using the svg Snap as SnapSVG or whatever you want to call it. The module loader approach is arguably better in almost any way you want to look at it... unless you need to ship tomorrow :).
Edit 2:
I just released v1.5.0 of Angular Snap which makes the Snap.js constructor an injected dependency rather than something we just look for on the window. You could now provide your own constructor, maybe saving it before it gets clobbered:
myApp.config(function(SnapConstructorProvider) {
SnapConstructorProvider.use(window.Snap);
});
Using this you'll still be able to take advantage of the snap-content directive even if you pull in the Snap.js script with a module loader.

Related

angular intro.js not available

I have been trying to use angular intro js in my mockup angular js project the modal that asks whether the user needs to go through the tutorial is visible, However when I click the ok button that invokes the callMe method , an error is printed in the console stating,
message:"Intro.js is not available. Make sure it is properly loaded."
name:"Introjs not available."
Could anyone suggest where I am going wrong?
Make sure you have refered the angular-intro library and also injected as a dependency.
Reference:
<script src="intro.min.js"></script>
<script src="angular-intro.js"></script>
<script src="app.js"></script>
Module:
var app = angular.module('myApp', ['angular-intro']);
DEMO
Just to add to Sajeetharan's comment: It turns out that the order of dependency MATTERS. You must include the intro.js first, then angular-intro.js, then the main app.js.
Otherwise, you might get
Intro.js is not available. Make sure it is properly loaded." name:"Introjs not available.

dealing with systemjs load time and sequence - there must be a better way

I have a situation using system.js with an angular application where I need to be able to include specific System.import(f) statements on a per-page basis, but it was imperative that they all be included before angular finishes bootstrapping and loading up its module.
I spent a long time on this problem and eventually this is the workaround I devised;
in my config.js, I am doing this...
config.js
// .... configuration ... //
Promise.all([
System.import('jquery'),
System.import('angular'),
System.import('angular.ng'),
System.import('bootstrap')
]).then(function() {
$(document).on('angular', function() {
angular.bootstrap(document, ['module-name']); $('body').removeClass('cloak');
});
});
Then I have a css class named .cloak. I tried ng-cloak but found it wasn't doing the job (I suspect because I'm deferring the angular bootstrapping)
.cloak { visibility: hidden; }
then on my individual page, I use this sort of code to shoe-horn my page-specific imports and finalize the process.
<!-- Load SystemJS -->
<script src="assets/js/system.js"></script>
<script src="config.js"></script>
<script>
System.import('app/main').then(function (e) {
Promise.all([
System.import('app/controllers/index'),
System.import('app/controllers/read'),
System.import('app/controllers/edit/article'),
System.import('scripts/lib/init')
]).then(function (m) {
$(document).trigger('angular');
});
});
</script>
So that's the basic idea; I don't allow angular to finish wiring up its module until everything has been imported through system.js. At present, this seems to work fine.
My problem is that I'm not a very good programmer, nor am I very clever. This seems like an extremely standard, normal problem that comes with the way system.js is designed and it occurs to me that there has to be a better, built in solution that I'm missing or haven't found.
Has anyone else dealt with this before that can offer some advice?
The reason I need to defer the module wiring is because I've got various angular controllers and models and such and I don't want them all to load on every page. (I mean, trimming down the scripts to only the ones needed at the moment is one of the points of a module loader, aside dependency resolution).
Trying to use the ng-app directive was constantly causing trouble - as angular would try to load before everything was finished and loaded in, so it had trouble finding things like certain controllers and the like on certain pages.
The biggest reason I need an alternative is that this method doesn't work well for minifying typescript.
This is an extremely standard issue with ng-cloak in general. Perhaps a better way has come around, but pretty much since I started working with angular I've just defined ng-cloak in the header of my index.html file like this:
<style>
[ng\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak {
display: none !important;
}
</style>
and added class="ng-cloak" to the body tag of my page. It works great and when Angular finishes loading it's internal ng-cloak styles effectively overwrite mine.
It seems like moving the inline script basically as is, to an external file, would still allow it to run exactly as you have it and then minification and such would be fine.
It also sounds like you're not creating a SPA here, since if I understand you correctly, you're calling config.jss from each page. You may want to reconsider that and go with a SPA. You will likely end up loading everything up front, but you'll load it all only once.

#section syntax instead of requirejs or browserify for angularjs application

I understand that requirejs and browserify can load my files dependent on its current context, and that it is amazing. I would really prefer to use the #section sections syntax that the razor engine uses. Was just wondering if there is a way to implement this into a typescript / angularjs application.
for example
index.html
#renderSection scripts;
// which could turn into something like
<script data-render="scripts"></scripts>
// the app.run() could declare all the scripts that will be needed on every
// page view
view.html
<script ng-section-repeat="injected in injection"></script>
// the ng-section-repeat is basically taking all the items in the
// typescript constructor and then finding out which ones are needed for
// that view.
I like the idea injecting application file dependencies in the view , without a configuration file and all the added extras that comes with the loaders.
I just want to easily define what files are needed in the actual view and get them loaded, with angular's dependency injection handling the dependency itself.
If you are handling all your dependencies with $inject then , as far as i can tell, dependency is technically already setup in the controllers, all one would need, is to load this as it is called. Which could even eliminate the need for the #section scripts completely
Update:
What i have done to sort of replicate the module loaders is to just use gulp-concat and define the file order in my gulp.config.js and then pass it to the gulp-src before running $.concat .this allows me to have the files in the gulp steam , in dependent order . They are however loaded on the first load. With gulp-uglify the files are tiny ( its now at 566Kb with 16 external libraries loading in 69ms . To put that into perspective it takes 209ms to load one google font ).
I dont know maybe i am not understanding browserify correctly but i honestly struggle to see the need for it, its seems extremely convoluted for something so simple
It is possible using external modules and an injector to do what you asked for:
I just want to easily define what files are needed in the actual view
import {UserFactory} from 'models/userFactory';
import {UserValidator} from 'models/userValidator';
import {Inject} from 'angular2/di';
and get them loaded, with angular's dependency injection handling the dependency itself.
Note: My example uses angular 2.x because I less familiar with angular 1.x and I'm sure you can do something really similar...
class SomeComponent {
userName: string;
userRating: number;
rating: number;
constructor(
#Inject(UserFactory) UserFactory
#Inject(UserValidator) UserValidator
)
{
this.UserFactory = UserFactory;
this.UserValidator = UserValidator;
}
}
Then you can use Browserify to create a bundle.js file that can be executed in a web browser.

Material Design Lite rendering problems with Angular JS

I have some problems using Material Design Lite (getmdl.io). I followed the steps showed in the getmdl.io web in order to install it (actually I use bower), but I always have the same problem, when I change the ng-route in my web, some resources don't render properly, I need to reload the page to get it properly rendered, for example.
First I have this:
then when I reload, I get what I want:
What I cant understand is why other resources like google icons or buttons work correctly but the menu button on the nav bar and other resources like this one need to reaload the page in order to render properly.
I try to include the library using the hosted method and bower method.
Any idea what is going on?
i past in my code this function
angular.module('app', ['ngRoute']).
run(function($rootScope, xxxx, xxx){
$rootScope.$on('$viewContentLoaded', function(event, next) {
componentHandler.upgradeAllRegistered();
});
});
It worked perfect! Good luck..
Libraries like MDL work by waiting for the page to load using the DOMContentLoaded event, scanning the page for things like input elements and manipulating them with JavaScript so that they can inject the bits and pieces needed to work with their components. This works fine on static websites, but the DOMContentLoaded event only fires once, so when Angular performs a page transition, the DOM changes without MDL knowing about it.
Material Design Lite has a section in its FAQ about using MDL on dynamic websites:
Material Design Lite will automatically register and render all elements marked with MDL classes upon page load. However in the case where you are creating DOM elements dynamically you need to register new elements using the upgradeElement function. Here is how you can dynamically create the same raised button with ripples shown in the section above:
<div id="container"/>
<script>
var button = document.createElement('button');
var textNode = document.createTextNode('Click Me!');
button.appendChild(textNode);
button.className = 'mdl-button mdl-js-button mdl-js-ripple-effect';
componentHandler.upgradeElement(button);
document.getElementById('container').appendChild(button);
</script>
Of course, this probably isn't terribly easy to do in your case, since you'd have to manually find each new element and call upgradeElement on it.
Usually, instead of doing this sort of event-based DOM manipulation, Angular uses directives to initiate DOM changes. Consider using a library built to interoperate with Angular, instead, such as Angular Material.

Angular translate extend existing translations

I am trying to have external modules change my $translateProvider.translation on the main module. see this as a "tranlation plugin" for my app.
it seems like changing translations from the $translate service is not possible.
mymodule.service('MyService', function ($translateProvider) {
var lib = function () {
//EDITED FOR BREVITY
this._registerTranslations = function (ctrl) {
if (!ctrl.i18n) return;
for (var name in ctrl.i18n) {
/////////////////////////////
// THIS IS THE PLACE, OBVIOUSLY PROVIDER IS NOT AVAILABLE!!!!
$translateProvider.translations(name, ctrl.i18n[name]);
//////////////////////////////
}
};
//EDITED FOR BREVITY
};
return new lib();
});
anyone with a bright idea?
So, to answer your question: there's no way to extend existing translations during runtime with $translate service without using asynchronous loading. I wonder why you want to do that anyway, because adding translations in such a way means that they are already there (otherwise you would obviously use asynchronous loading).
Have a look at the Asynchronous loading page. You can create a factory that will load a translation from wherever you want.
I created an Angular constant to hold new translations. If I want to add a new translation, I add it to the constant. Then in my custom loader, I first check the constant to see if the translation exists (either a new one, or an updated one). If so, I load it from the constant. If not, I load it from a .json file (or wherever you load your initial translations from). Use $translate.refresh() to force translations to be reloaded and reevaluated.
Demo here
The demo is pretty simple. You would need to do a little more work if you wanted to just change a subset of the translations, but you get the general idea.
From the AngularJS docs (https://docs.angularjs.org/guide/providers):
You should use the Provider recipe only when you want to expose an API for application-wide configuration that must be made before the application starts. This is usually interesting only for reusable services whose behavior might need to vary slightly between applications.
Providers are to be used with the application's .config function. $translateProvider for configuration, $translate for other services and controllers.

Resources