By Jan Antala / @janantala
WebElement #25 feat. Slovak AngularJS #3
Bratislava, 5th December 2013
front-end dev
at apptives
student
at FIIT STU
angular-[optional-namespace]-[thing-name]-[optional-thing-type]
Example:
angular-qr
angular-adaptive-speech
Specification for reusable AngularJS components: angular-component-spec
Choosing an OSS license doesn’t need to be scary
src/
angular-adaptive-detection.js
test/
test.conf.js
unit.spec.js
.bowerrc
.gitignore
.travis.yml
CHANGELOG.md
CONTRIBUTING.md
Gruntfile.js
LICENSE
angular-adaptive-detection.js
angular-adaptive-detection.min.js
bower.json
package.json
module.exports = function (grunt) {
grunt.loadNpmTasks('grunt-task');
grunt.registerTask('default', ['task1', 'task2']);
// Project configuration.
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
task1: {
options: {
...
}
}
...
});
};
Before:
grunt.loadNpmTasks('grunt-karma');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-concurrent');
After:
require('load-grunt-tasks')(grunt);
(function () {
'use strict';
var adaptive = angular.module('adaptive.detection', []);
// ...
});
angular.module('myApp', ['adaptive.detection']);
adaptive.provider('$detection', [function() {
this.setUserAgent = function(userAgent) {
this.userAgent = userAgent;
};
this.$get = function() {
...
return {
...
}
};
}]);
angular.module('myApp').config(function($detectionProvider){
$detectionProvider.setUserAgent('angular');
});
this.$get = function() {
var userAgent = this.userAgent;
return {
getUserAgent: function(){
return userAgent;
},
isiOS: function(){
return (/(iPad|iPhone|iPod)/gi).test(userAgent);
},
isAndroid: function(){
return (/(Android)/gi).test(userAgent);
}
}
};
angular.module('myApp')
.controller('MainCtrl', function($scope, $detection){
$scope.detection = $detection;
});
$detection.isiOS(): {{detection.isiOS()}}
$detection.isAndroid(): {{detection.isAndroid()}}
$detection.getUserAgent():
{{detection.getUserAgent()}}
You can use gh-pages branch.
python -m SimpleHTTPServer
module.exports = function(config) {
config.set({
basePath: '..',
files: [
'bower_components/angular/angular.js',
'bower_components/angular-mocks/angular-mocks.js',
'src/angular-adaptive-detection.js',
'test/*.spec.js'
],
frameworks: ['jasmine'],
singleRun: true,
browsers: [ 'Chrome' ]
});
};
var karmaConfig = function(configFile, customOptions) {
var options = { configFile: configFile, keepalive: true };
var travisOptions = process.env.TRAVIS && { browsers: ['Firefox'], reporters: 'dots' };
return grunt.util._.extend(options, customOptions, travisOptions);
};
karma: {
unit: {
options: karmaConfig('test/test.conf.js')
}
},
describe('adaptive.detection', function(){
describe('provider functionality', function() {
// ...
});
describe('public methods', function() {
// ...
});
// ...
});
var detection;
beforeEach(module('adaptive.detection', function($detectionProvider) {
detection = $detectionProvider;
}));
it('should be defined', inject(function() {
expect(detection).toBeDefined();
}));
it('should have setUserAgent method', inject(function() {
expect(detection.setUserAgent).toBeDefined();
expect(typeof detection.setUserAgent).toBe('function');
}));
it('should have $get method', inject(function() {
expect(detection.$get).toBeDefined();
expect(typeof detection.$get).toBe('function');
}));
it('should be defined', inject(function($detection) {
expect($detection).toBeDefined();
}));
it('should have public methods', inject(function($detection) {
expect($detection.getUserAgent).toBeDefined();
expect($detection.isiOS).toBeDefined();
expect($detection.isAndroid).toBeDefined();
expect(typeof $detection.getUserAgent).toBe('function');
expect(typeof $detection.isiOS).toBe('function');
expect(typeof $detection.isAndroid).toBe('function');
}));
describe('test Android', function() {
beforeEach(module('adaptive.detection', function($detectionProvider) {
$detectionProvider.setUserAgent('Android');
}));
it('should detect Android browser', inject(function($detection) {
expect($detection.isAndroid()).toEqual(true);
expect($detection.isiOS()).toEqual(false);
}));
});
Writing AngularJS Documentation
Extends jsdoc
All the docs are stored inline in the source code
and so is kept in sync as the code changes.
I have a grunt task for that!
<type>(<scope>): <subject>
<BLANK LINE>
<body>
<BLANK LINE>
<footer>
Includes motivation for the change and contrasts with previous behavior
Include description of the change, justification and migration notes
Closed bugs should be listed on a separate line in the footer prefixed with "Closes" keyword.
Closes #123, #245, #992
feat($browser): onUrlChange event (popstate/hashchange/polling)
Added new event to $browser:
- forward popstate event if available
- forward hashchange event if popstate not available
- do polling when neither popstate nor hashchange available
Breaks $browser.onHashChange, which was removed (use onUrlChange instead)
language: node_js
node_js:
- "0.10"
before_install:
- export DISPLAY=:99.0
- sh -e /etc/init.d/xvfb start
- npm install -g bower grunt-cli
- npm install
- bower install
script: "grunt"
bower register <my-package-name> <git-endpoint>
bower register angular-adaptive-detection
git://github.com/angular-adaptive/adaptive-detection.git
bower install angular-adaptive-detection
bower install angular-adaptive/adaptive-detection
bower install git://github.com/angular-adaptive/adaptive-detection.git
I have a grunt task for that!
changelog: {
options: {
dest: 'CHANGELOG.md'
}
},
bump: {
files: ['package.json', 'bower.json'],
updateConfigs: ['pkg']
},
uglify: {
options: { preserveComments: 'some' },
dist: {
src: '<%= pkg.name %>.js',
dest: '<%= pkg.name %>.min.js'
}
},
concat: {
options: {
process: true,
banner: '<%= meta.banner %>\n\n'
},
dist: {
src: 'src/<%= pkg.name %>.js',
dest: '<%= pkg.name %>.js'
}
},
mention @AngularJS
hashtag #AngularJS
Slides:
janantala.com/slides/how-to-build-an-open-source-angularjs-module