├── .gitignore
├── LICENSE
├── README.md
├── demo
├── controllers
│ └── demo.js
├── index.html
└── resources
│ └── styles
│ └── demo.css
├── package.json
└── source
├── Makefile
├── angular-material-badge.css
└── angular-material-badge.js
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | yarn.lock
3 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Juan Manuel Mouriz
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # angular-material-badge
2 |
3 | Material Badge for AngularJS
4 |
5 | ## Demo
6 |
7 | View [online demo](https://jmouriz.github.io/angular-material-badge/demo/demo.html)
8 |
9 | ## Install
10 |
11 | Download the package:
12 |
13 | ```
14 | yarn add angular-material-badge
15 | ```
16 |
17 | ## Usage
18 |
19 | In your document head, include:
20 |
21 | ```html
22 |
23 | ```
24 |
25 | Use the md-badge where you wish:
26 |
27 | ```html
28 | 12
29 |
30 |
31 | ```
32 |
33 | Then, just before close body tag, include:
34 |
35 | ```html
36 |
37 | ```
38 |
39 | Include the module in your application:
40 |
41 | ```javascript
42 | var application = angular.module('Application', ['ngMdBadge']);
43 | ```
44 |
--------------------------------------------------------------------------------
/demo/controllers/demo.js:
--------------------------------------------------------------------------------
1 | var demo = angular.module('Demo', ['ngMaterial', 'ngMdIcons', 'ngMdBadge', 'hc.marked']);
2 |
3 | demo.config(['markedProvider', function(markedProvider) {
4 | markedProvider.setOptions({
5 | gfm: true,
6 | tables: true,
7 | highlight: function(code, language) {
8 | if (!language) {
9 | language = 'bash';
10 | } else if (language == 'html') {
11 | language = 'markup';
12 | }
13 | return Prism.highlight(code, Prism.languages[language]);
14 | }
15 | });
16 | }]);
17 |
18 | var themes = [{
19 | name: 'red',
20 | description: 'Red'
21 | }, {
22 | name: 'green',
23 | description: 'Green'
24 | }, {
25 | name: 'blue',
26 | description: 'Blue'
27 | }, {
28 | name: 'orange',
29 | description: 'Orange'
30 | }, {
31 | name: 'indigo',
32 | description: 'Indigo'
33 | }, {
34 | name: 'pink',
35 | description: 'Pink'
36 | }, {
37 | name: 'teal',
38 | description: 'Teal'
39 | }, {
40 | name: 'purple',
41 | description: 'Purple'
42 | }, {
43 | name: 'yellow',
44 | description: 'Yellow'
45 | }, {
46 | name: 'brown',
47 | description: 'Brown'
48 | }, {
49 | name: 'grey',
50 | description: 'Grey'
51 | }, {
52 | name: 'cyan',
53 | description: 'Cyan'
54 | }, {
55 | name: 'lime',
56 | description: 'Lime'
57 | }, {
58 | name: 'amber',
59 | description: 'Amber'
60 | }];
61 |
62 | demo.config(['$mdThemingProvider', function($mdThemingProvider) {
63 | $mdThemingProvider.theme('default').primaryPalette('purple').accentPalette('blue-grey').warnPalette('red');
64 | $mdThemingProvider.theme('blue').primaryPalette('blue').accentPalette('blue-grey').warnPalette('red');
65 | $mdThemingProvider.theme('red').primaryPalette('red').accentPalette('blue-grey').warnPalette('red');
66 | $mdThemingProvider.theme('green').primaryPalette('green').accentPalette('blue-grey').warnPalette('red');
67 | $mdThemingProvider.theme('pink').primaryPalette('pink').accentPalette('blue-grey').warnPalette('red');
68 | $mdThemingProvider.theme('orange').primaryPalette('orange').accentPalette('blue-grey').warnPalette('red');
69 | $mdThemingProvider.theme('indigo').primaryPalette('indigo').accentPalette('blue-grey').warnPalette('red');
70 | $mdThemingProvider.theme('teal').primaryPalette('teal').accentPalette('blue-grey').warnPalette('red');
71 | $mdThemingProvider.theme('purple').primaryPalette('purple').accentPalette('blue-grey').warnPalette('red');
72 | $mdThemingProvider.theme('yellow').primaryPalette('yellow').accentPalette('blue-grey').warnPalette('red');
73 | $mdThemingProvider.theme('grey').primaryPalette('grey').accentPalette('blue-grey').warnPalette('red');
74 | $mdThemingProvider.theme('cyan').primaryPalette('cyan').accentPalette('blue-grey').warnPalette('red');
75 | $mdThemingProvider.theme('brown').primaryPalette('brown').accentPalette('blue-grey').warnPalette('red');
76 | $mdThemingProvider.theme('lime').primaryPalette('lime').accentPalette('blue-grey').warnPalette('red');
77 | $mdThemingProvider.theme('amber').primaryPalette('amber').accentPalette('blue-grey').warnPalette('red');
78 | $mdThemingProvider.alwaysWatchTheme(true);
79 | }]);
80 |
81 | demo.controller('Demo', ['$scope', function($scope) {
82 | $scope.theme = 'red';
83 | $scope.themes = themes;
84 | $scope.show = true;
85 | }]);
86 |
--------------------------------------------------------------------------------
/demo/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | test
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | AngularJS Material Badge online Demo
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 | {{theme.description}}
26 |
27 |
28 |
29 | Show
30 |
31 |
32 |
33 |
34 |
35 | Badge demo
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 | {{value}}
47 |
48 |
49 |
50 |
51 | Badge Demo
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/demo/resources/styles/demo.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 24px;
3 | }
4 |
5 | .test {
6 | align-self: center;
7 | }
8 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "angular-material-badge",
3 | "version": "1.2.91",
4 | "description": "Material Badge for AngularJS",
5 | "main": "angular-material-badge.js",
6 | "repository": "https://github.com/jmouriz/angular-material-badge",
7 | "author": "Juan Manuel ",
8 | "license": "MIT",
9 | "dependencies": {
10 | "angular": "^1.6.5",
11 | "angular-animate": "^1.6.5",
12 | "angular-aria": "^1.6.5",
13 | "angular-material": "^1.1.4"
14 | },
15 | "devDependencies": {
16 | "angular-marked": "^1.2.2",
17 | "angular-material-icons": "^0.7.1",
18 | "minify": "^3.0.1",
19 | "prismjs": "^1.6.0"
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/source/Makefile:
--------------------------------------------------------------------------------
1 | PACKAGE := $(shell grep name ../package.json | head -1 | cut -d: -f2 | tr -d '" ,')
2 | SOURCE := $(PACKAGE)
3 | TARGET := ../build/$(PACKAGE).min
4 |
5 | all: $(TARGET).js $(TARGET).css
6 |
7 | $(TARGET).css: $(SOURCE).css
8 | @../node_modules/.bin/minify $< > $@
9 |
10 | $(TARGET).js: $(SOURCE).js
11 | @../node_modules/.bin/minify $< > $@
12 |
--------------------------------------------------------------------------------
/source/angular-material-badge.css:
--------------------------------------------------------------------------------
1 | .md-badge {
2 | background-color: rgb(0, 130, 130);
3 | border-image-outset: 0px;
4 | border-image-repeat: stretch;
5 | border-image-slice: 100%;
6 | border-image-source: none;
7 | color: rgb(255, 255, 255);
8 | border-radius: 10px;
9 | box-sizing: border-box;
10 | cursor: pointer;
11 | display: inline-block;
12 | font-family: Roboto, "Helvetica Neue", sans-serif;
13 | font-size: 11px;
14 | font-stretch: normal;
15 | font-style: normal;
16 | font-variant-caps: normal;
17 | font-variant-ligatures: normal;
18 | font-variant-numeric: normal;
19 | font-weight: normal;
20 | height: 20px;
21 | letter-spacing: 0.4px;
22 | line-height: 18px;
23 | min-width: 20px;
24 | padding-bottom: 0px;
25 | padding-left: 2px;
26 | padding-right: 2px;
27 | padding-top: 1px;
28 | text-align: center;
29 | text-indent: 0px;
30 | text-rendering: auto;
31 | text-shadow: none;
32 | text-size-adjust: 100%;
33 | text-transform: none;
34 | white-space: normal;
35 | word-spacing: 0px;
36 | z-index: 9999;
37 | writing-mode: horizontal-tb;
38 | -webkit-font-smoothing: antialiased;
39 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
40 | }
41 |
--------------------------------------------------------------------------------
/source/angular-material-badge.js:
--------------------------------------------------------------------------------
1 | /* onDOMChange: https://stackoverflow.com/a/3219767/1804902 */
2 | (function (window) {
3 | 'use strict';
4 |
5 | var last = +new Date();
6 | var delay = 100;
7 | var stack = [];
8 |
9 | function callback() {
10 | var now = +new Date();
11 | if (now - last > delay) {
12 | for (var i = 0; i < stack.length; i++) {
13 | stack[i]();
14 | }
15 | last = now;
16 | }
17 | }
18 |
19 | var onDOMChange = function(handler, _delay) {
20 | if (_delay) {
21 | delay = _delay;
22 | }
23 | stack.push(handler);
24 | };
25 |
26 | function native() {
27 | var last = document.getElementsByTagName('*');
28 | var _length = last.length;
29 | var timer = setTimeout(function check() {
30 | var current = document.getElementsByTagName('*');
31 | var length = current.length;
32 |
33 | if (length != _length) {
34 | last = [];
35 | }
36 |
37 | for (var i = 0; i < length; i++) {
38 | if (current[i] !== last[i]) {
39 | callback();
40 | last = current;
41 | _length = length;
42 | break;
43 | }
44 | }
45 |
46 | setTimeout(check, delay);
47 | }, delay);
48 | }
49 |
50 | var support = {};
51 | var element = document.documentElement;
52 | var remain = 3;
53 |
54 | function decide() {
55 | if (support.DOMNodeInserted) {
56 | window.addEventListener('DOMContentLoaded', function() {
57 | if (support.DOMSubtreeModified) {
58 | element.addEventListener('DOMSubtreeModified', callback, false);
59 | } else {
60 | element.addEventListener('DOMNodeInserted', callback, false);
61 | element.addEventListener('DOMNodeRemoved', callback, false);
62 | }
63 | }, false);
64 | } else if (document.onpropertychange) {
65 | document.onpropertychange = callback;
66 | } else {
67 | native();
68 | }
69 | }
70 |
71 | function test(event) {
72 | element.addEventListener(event, function handler() {
73 | support[event] = true;
74 | element.removeEventListener(event, handler, false);
75 | if (--remain === 0) {
76 | decide();
77 | }
78 | }, false);
79 | }
80 |
81 | if (window.addEventListener) {
82 | test('DOMSubtreeModified');
83 | test('DOMNodeInserted');
84 | test('DOMNodeRemoved');
85 | } else {
86 | decide();
87 | }
88 |
89 | /*
90 | var dummy = document.createElement('div');
91 | element.appendChild(dummy);
92 | element.removeChild(dummy);
93 | */
94 |
95 | window.onDOMChange = onDOMChange;
96 | })(window);
97 |
98 | (function(window, angular, document) {
99 | 'use strict';
100 |
101 | var module = angular.module('ngMdBadge', ['ngMaterial']);
102 |
103 | module.directive('mdBadge', ['$mdTheming', function($mdTheming) {
104 | return {
105 | restrict: 'E',
106 | replace: true,
107 | transclude: true,
108 | link: function(scope, element, attributes) {
109 | $mdTheming(element);
110 | },
111 | template: function(element, attributes) {
112 | return '';
113 | }
114 | };
115 | }]);
116 |
117 | module.directive('mdBadge', ['$mdTheming', '$mdColors', '$timeout', '$window', function($mdTheming, $mdColors, $timeout, $window) {
118 | return {
119 | restrict: 'A',
120 | link: function(scope, element, attributes) {
121 | $mdTheming(element);
122 | //
123 | var parent = element.parent();
124 | var badge = document.createElement('div');
125 | var offset = parseInt(attributes.mdBadgeOffset);
126 | if (isNaN(offset)) {
127 | offset = 10;
128 | }
129 | function style(where, color) {
130 | if (color) {
131 | if (color.startsWith(':')) {
132 | color = $mdColors.getThemeColor(color.substr(1));
133 | }
134 | badge.style[where] = color;
135 | }
136 | }
137 | badge.classList.add('md-badge');
138 | badge.style.position = 'absolute';
139 | parent.append(badge);
140 | scope.$watch(function() {
141 | return attributes.mdBadgeColor;
142 | }, function(value){
143 | style('color', value);
144 | });
145 | scope.$watch(function() {
146 | return attributes.mdBadgeFill;
147 | }, function(value){
148 | style('background-color', value);
149 | });
150 | scope.$watch(function() {
151 | return attributes.mdBadge;
152 | }, function(value){
153 | badge.textContent = value;
154 | badge.style.display = value ? 'initial' : 'none';
155 | });
156 | var position = function(value) {
157 | var top = element.prop('offsetTop');
158 | badge.style.display = attributes.mdBadge && top ? 'initial' : 'none';
159 | badge.style.left = value.left + value.width - 20 + offset + 'px';
160 | badge.style.top = value.top + value.height - 20 + offset + 'px';
161 | };
162 | scope.$watch(function() {
163 | return {
164 | top: element.prop('offsetTop'),
165 | left: element.prop('offsetLeft'),
166 | width: element.prop('offsetWidth'),
167 | height: element.prop('offsetHeight')
168 | };
169 | }, function(value) {
170 | position(value);
171 | }, true);
172 | $timeout(function() {
173 | scope.$digest();
174 | });
175 | var update = function() {
176 | position({
177 | top: element.prop('offsetTop'),
178 | left: element.prop('offsetLeft'),
179 | width: element.prop('offsetWidth'),
180 | height: element.prop('offsetHeight')
181 | });
182 | };
183 | angular.element($window).bind('resize', function(){
184 | update();
185 | });
186 | onDOMChange(function() {
187 | update();
188 | });
189 | },
190 | };
191 | }]);
192 | })(window, window.angular, document);
193 |
--------------------------------------------------------------------------------