├── .bowerrc
├── .gitignore
├── .travis.yml
├── Changelog.md
├── Contributors.md
├── Gruntfile.js
├── LICENSE.md
├── README.md
├── bower.json
├── dist
├── .gitkeep
├── angular-semantic-ui.js
└── angular-semantic-ui.min.js
├── karma.conf.js
├── package.json
└── src
├── accordion
├── README.md
├── accordion.js
├── docs
│ ├── .gitkeep
│ ├── controllers.js
│ └── demo.html
└── test
│ ├── .gitkeep
│ └── accordion.spec.js
├── angularify.semantic.js
├── checkbox
├── README.md
├── checkbox.js
├── docs
│ ├── controllers.js
│ └── demo.html
└── test
│ ├── .gitkeep
│ └── checkbox.spec.js
├── dimmer
├── README.md
├── dimmer.js
├── docs
│ ├── controllers.js
│ └── demo.html
└── test
│ └── .gitkeep
├── dropdown
├── README.md
├── docs
│ ├── controllers.js
│ └── demo.html
├── dropdown.js
└── test
│ └── dropdown.spec.js
├── modal
├── README.md
├── docs
│ ├── controllers.js
│ └── demo.html
├── modal.js
└── test
│ └── modal.spec.js
├── popup
├── README.md
├── docs
│ ├── controllers.js
│ └── demo.html
├── popup.js
└── test
│ └── popup.spec.js
├── rating
├── README.md
├── docs
│ ├── controllers.js
│ └── demo.html
├── rating.js
└── test
│ └── rating.spec.js
├── sidebar
├── README.md
├── docs
│ ├── controllers.js
│ └── demo.html
├── sidebar.js
└── test
│ └── sidebar.spec.js
└── wizard
├── README.md
├── doc
├── controllers.js
└── demo.html
├── test
└── wizard.spec.js
└── wizard.js
/.bowerrc:
--------------------------------------------------------------------------------
1 | {
2 | "directory": "bower_components"
3 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .dev/
2 | .tmp/
3 | .DS_Store
4 | *.sublime-project
5 | *.sublime-workspace
6 | bower_components/
7 | node_modules/
8 | /pages/
9 | /docs/
10 | /test/coverage/
11 | !.gitignore
12 | css/
13 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - "0.8"
4 |
5 | before_script:
6 | - npm install --quiet -g grunt-cli karma
7 | - npm install
8 |
9 | script: grunt test && grunt build
10 |
--------------------------------------------------------------------------------
/Changelog.md:
--------------------------------------------------------------------------------
1 | 0.0.3 [Released]
2 | =============================
3 |
4 | * Animated modal
5 | * Destroy listener was being called to destroy an accordion in the dropdown module
6 | * Corrected spelling in accordion README.md
7 | * Use semantic ui classes instead of inline style in the sidebar module
8 |
9 |
10 | 0.0.2 [Released]
11 | =============================
12 |
13 | * Added wizard directive
14 | * Fixes to dropdown to update model, and allow for {{variables}} as title
15 | * Code clean up and grunt task optimization
16 | * Fixed scope issue with accordion
17 | * Updated modal to use ng-class
18 | * Updated accordion to use ng-class
19 | * Updated sidebar to use semantic-ui javascript functions
20 | * Updated README.md
21 | * Corrected spelling in rating module
22 | * Corrected opening problem for the dropdown
23 |
24 |
25 | 0.0.1 [Released]
26 | =============================
27 |
28 | * Initial release;
29 | * Added `grunt build` task;
30 | * Added `grunt test` task;
31 | * Added `karma` for testing;
32 | * `accordion` - initial release;
33 | * `checkbox` - initial release;
34 | * `dimmer` - initial release;
35 | * `dropdown` - initial release;
36 | * `modal` - initial release;
37 | * `popup` - initial release;
38 | * `rating` - initial release;
39 | * `sidebar` - initial release.
--------------------------------------------------------------------------------
/Contributors.md:
--------------------------------------------------------------------------------
1 | Author:
2 |
3 | * [0xAX](https://twitter.com/0xAX)
4 |
5 | Maintainer:
6 | * [jspdown](https://github.com/jspdown)
7 |
8 | Contributors:
9 |
10 | * [Nikita K.](https://github.com/Mendor)
11 | * [StudioThree10](https://github.com/studiothree10)
12 | * [cgroner](https://github.com/cgroner)
13 | * [solcates](https://github.com/solcates)
14 | * [xblaster](https://github.com/xblaster)
15 | * [frankt117](https://github.com/frankt117)
16 | * [tombee](https://github.com/tombee)
17 | * [dszczyt](https://github.com/dszczyt)
18 | * [RomainLanz](https://github.com/RomainLanz)
19 | * [KapuzenSohn](https://github.com/KapuzenSohn)
20 | * [Kurmaev](https://github.com/Kurmaev)
21 | * [rex](https://github.com/rex)
22 | * [kevspadilla](https://github.com/kevspadilla)
23 | * [Virviil](https://github.com/Virviil)
24 |
--------------------------------------------------------------------------------
/Gruntfile.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | module.exports = function(grunt) {
3 |
4 | grunt.loadNpmTasks('grunt-contrib-watch');
5 | grunt.loadNpmTasks('grunt-contrib-concat');
6 | grunt.loadNpmTasks('grunt-contrib-copy');
7 | grunt.loadNpmTasks('grunt-contrib-jshint');
8 | grunt.loadNpmTasks('grunt-contrib-uglify');
9 | grunt.loadNpmTasks('grunt-html2js');
10 | grunt.loadNpmTasks('grunt-karma');
11 | grunt.loadNpmTasks('grunt-conventional-changelog');
12 | grunt.loadNpmTasks('grunt-ngdocs');
13 |
14 | grunt.initConfig({
15 | dist: 'dist',
16 | filename: 'angular-semantic-ui',
17 | pkg: grunt.file.readJSON('package.json'),
18 | concat: {
19 | js: {
20 | src: ['src/angularify.semantic.js',
21 | 'src/accordion/accordion.js',
22 | 'src/checkbox/checkbox.js',
23 | 'src/dimmer/dimmer.js',
24 | 'src/dropdown/dropdown.js',
25 | 'src/modal/modal.js',
26 | 'src/popup/popup.js',
27 | 'src/sidebar/sidebar.js',
28 | 'src/rating/rating.js',
29 | 'src/wizard/wizard.js',
30 | ],
31 | dest: '<%= dist %>/<%= filename %>.js'
32 | }
33 | },
34 | uglify: {
35 | dist: {
36 | src: ['<%= dist %>/<%= filename %>.js'],
37 | dest: '<%= dist %>/<%= filename %>.min.js'
38 | }
39 | },
40 | karma: {
41 | options: {
42 | configFile: 'karma.conf.js'
43 | },
44 | watch: {
45 | background: true
46 | },
47 | continuous: {
48 | singleRun: true
49 | },
50 | },
51 | watch: {
52 | javascript: {
53 | files: ['src/**/*.js'],
54 | tasks: ['concat:js', 'uglify']
55 | }
56 |
57 | }
58 | });
59 |
60 | grunt.registerTask('build', ['concat:js', 'uglify']);
61 | grunt.registerTask('test', ['karma']);
62 | grunt.registerTask('default', ['concat:js', 'uglify', 'watch:javascript']);
63 | };
64 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | The MIT License
2 |
3 | Copyright (c) 2014 0xAX
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6 |
7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8 |
9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | angular-semantic-ui
2 | ======================
3 |
4 | `angular-semantic-ui` - is a set of `angular.js` directives for [semantic-ui](http://semantic-ui.com/).
5 |
6 | Directives
7 | ----------------------
8 |
9 | * [accordion](https://github.com/angularify/angular-semantic-ui/tree/master/src/accordion)
10 | * [checkbox](https://github.com/angularify/angular-semantic-ui/tree/master/src/checkbox)
11 | * [dimmer](https://github.com/angularify/angular-semantic-ui/tree/master/src/dimmer)
12 | * [dropdown](https://github.com/angularify/angular-semantic-ui/tree/master/src/dropdown)
13 | * [modal](https://github.com/angularify/angular-semantic-ui/tree/master/src/modal)
14 | * [popup](https://github.com/angularify/angular-semantic-ui/tree/master/src/popup)
15 | * [rating](https://github.com/angularify/angular-semantic-ui/tree/master/src/rating)
16 | * [sidebar](https://github.com/angularify/angular-semantic-ui/tree/master/src/sidebar)
17 | * [wizard](https://github.com/angularify/angular-semantic-ui/tree/master/src/wizard)
18 |
19 | **IMPORTANT** angular-semantic-ui is only 0.0.2, and **NOT PRODUCTION READY**.
20 |
21 | Installation
22 | ----------------------
23 |
24 | ```
25 | $ bower install angular-semantic-ui
26 | ```
27 |
28 |
29 | Building
30 | ----------------------
31 |
32 | Get main [repo](https://github.com/angularify/angular-semantic-ui) with:
33 |
34 | ```
35 | $ git clone https://github.com/angularify/angular-semantic-ui.git
36 | ```
37 |
38 | Than go to the `angular-semantic-ui` directory and install dependencies:
39 |
40 | ```
41 | $ npm install && bower install
42 | ```
43 |
44 | Then execute:
45 |
46 | ```
47 | $ grunt build && grunt test
48 | ```
49 |
50 | There will be: `dist/angular-semantic-ui.js`.
51 |
52 | Contribution
53 | ----------------------
54 |
55 | 1. Fork main [repo](https://github.com/angularify/angular-semantic-ui)
56 | 2. Make changes.
57 | 3. Add tests.
58 | 4. Send pull request.
59 | 5. Thank you.
60 |
61 | Author
62 | ----------------------
63 |
64 | [@0xAX](https://twitter.com/0xAX)
65 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "angular-semantic-ui",
3 | "description": "Angular - AngularJS directives for Semantic UI.",
4 | "version": "0.0.3",
5 | "keywords": [
6 | "angular",
7 | "ui"
8 | ],
9 | "homepage": "http://solcates.github.io/angular-semantic-ui",
10 | "bugs": "https://github.com/solcates/angular-semantic-ui",
11 | "author": {
12 | "name": "Alex Kuleshov",
13 | "url": "https://github.com/0xAX"
14 | },
15 | "repository": {
16 | "type": "git",
17 | "url": "https://github.com/solcates/angular-semantic-ui.git"
18 | },
19 | "licenses": [
20 | {
21 | "type": "MIT",
22 | "url": "https://github.com/solcates/angular-semantic-ui/blob/master/LICENSE.md"
23 | }
24 | ],
25 | "main": [
26 | "dist/angular-semantic-ui.js"
27 | ],
28 | "ignore": [
29 | "docs",
30 | "test",
31 | "CONTRIBUTING.md"
32 | ],
33 | "dependencies": {
34 | "angular": "latest",
35 | "semantic": "latest"
36 | },
37 | "devDependencies": {
38 | "angular-mocks" : "latest"
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/dist/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/angularify/angular-semantic-ui/6ac38e0bc5c91b084fae8defecb9e3e9ed74c3a8/dist/.gitkeep
--------------------------------------------------------------------------------
/dist/angular-semantic-ui.js:
--------------------------------------------------------------------------------
1 | angular.module('angularify.semantic', ['angularify.semantic.accordion',
2 | 'angularify.semantic.checkbox',
3 | 'angularify.semantic.dimmer',
4 | 'angularify.semantic.dropdown',
5 | 'angularify.semantic.modal',
6 | 'angularify.semantic.popup',
7 | 'angularify.semantic.rating',
8 | 'angularify.semantic.sidebar',
9 | 'angularify.semantic.wizard']);
10 |
11 | 'use strict';
12 |
13 | angular.module('angularify.semantic.accordion', [])
14 |
15 | .controller('AccordionController', ['$scope', function($scope){
16 | $scope.accordions = [];
17 |
18 | this.add_accordion = function(scope) {
19 | $scope.accordions.push(scope);
20 |
21 | var _this = this;
22 | scope.$on('$destroy', function (event) {
23 | _this.remove_accordion(scope);
24 | });
25 |
26 | return $scope.accordions;
27 | }
28 |
29 | this.closeAll = function(scope) {
30 | var i = 0;
31 | var isCloseAll = false;
32 |
33 | var index = $scope.accordions.indexOf(scope);
34 |
35 | for (i in $scope.accordions){
36 | if ($scope.accordions[i].close)
37 | isCloseAll = true;
38 | }
39 |
40 | if (isCloseAll == true){
41 | for (i in $scope.accordions){
42 | if (i !== index) {
43 | $scope.accordions[i].active = false;
44 | }
45 | }
46 |
47 | return true;
48 | }
49 |
50 | return false;
51 |
52 | }
53 |
54 | this.remove_accordion = function(scope) {
55 | var index = $scope.accordions.indexOf(scope);
56 | if ( index !== -1 ) {
57 | $scope.accordions.splice(index, 1);
58 | }
59 | }
60 |
61 | this.is_close_all = function() {
62 | var i = 0;
63 |
64 | for (i in $scope.accordions){
65 | if ($scope.accordions[i].close == 'true')
66 | return true;
67 | }
68 | return false;
69 | }
70 | }])
71 |
72 | .directive('accordion', function () {
73 | return {
74 | restrict: 'E',
75 | replace: true,
76 | transclude: true,
77 | controller: 'AccordionController',
78 | scope: {
79 | 'close': '@'
80 | },
81 | template: "
",
82 | link: function(scope, element, attrs, AccordionController) {
83 |
84 | if(typeof attrs.styled !== 'undefined') {
85 | element.addClass('styled');
86 | }
87 |
88 | AccordionController.add_accordion(scope);
89 | }
90 | }
91 | })
92 |
93 | .directive('accordionGroup', function() {
94 | return {
95 | restrict: 'E',
96 | replace: true,
97 | transclude: true,
98 | scope : {
99 | title: '@',
100 | open: '@'
101 | },
102 | require:'^accordion',
103 | template: "\
104 |
\
105 | \
106 | {{ title }} \
107 |
\
108 |
\
109 |
\
110 |
",
111 |
112 | link: function(scope, element, attrs, AccordionController) {
113 |
114 | // set up active
115 | scope.active = attrs.open === 'true';
116 |
117 | // Add the accordion to the controller
118 | AccordionController.add_accordion(scope);
119 |
120 | // Click handler
121 | scope.click_on_accordion_tab = function(){
122 |
123 | // class all first of all
124 | AccordionController.closeAll(scope);
125 |
126 | // Swap the active state
127 | scope.active = !scope.active;
128 |
129 | // Add animation to the accordion group content
130 | element.children().last().slideToggle();
131 | };
132 | }
133 | };
134 | });
135 | 'use strict';
136 |
137 | angular.module('angularify.semantic.checkbox', [])
138 | .directive('checkbox', function() {
139 | return {
140 | restrict: 'E',
141 | replace: true,
142 | transclude: true,
143 | scope: {
144 | checked: '&?',
145 | disabled: '&?',
146 | ngModel: '=ngModel'
147 | },
148 | controller: function() {
149 | var vm = this;
150 |
151 | // TODO: assert this is usefull ?
152 | // if(angular.isUndefined(vm.ngModel)) { vm.ngModel = !!vm.ngModel; }
153 |
154 | if(angular.isFunction(vm.checked)) { vm.ngModel = !!vm.checked(); }
155 |
156 | vm.toggle = function() {
157 | if(angular.isFunction(vm.disabled) && vm.disabled()) return;
158 | vm.ngModel = !vm.ngModel;
159 | }
160 | },
161 | controllerAs: 'vm',
162 | bindToController: true,
163 | require: 'ngModel',
164 | template: '' +
165 | ' ' +
166 | ' ' +
167 | '
',
168 | link: function() { }
169 | };
170 | });
171 |
172 | 'use strict';
173 |
174 | angular.module('angularify.semantic.dimmer', [])
175 |
176 | .directive("pageDimmer", function () {
177 | return {
178 | restrict: 'E',
179 | replace: true,
180 | transclude: true,
181 | scope : {
182 | show : "=?",
183 | model: '=ngModel'
184 | },
185 | template: "",
190 | link : function(scope, element, attrs, ngModel) {
191 |
192 | if (scope.show == true) {
193 | scope.dimmer_class = 'ui page active dimmer';
194 | }
195 | else {
196 | scope.show = false;
197 | scope.dimmer_class = 'ui page disable dimmer';
198 | }
199 |
200 | //
201 | // Click on dimmer handler
202 | //
203 | scope.click_on_dimmer = function(){
204 | scope.model = false;
205 | scope.dimmer_class = 'ui page dimmer';
206 | }
207 |
208 | //
209 | // Watch for the ng-model changing
210 | //
211 | scope.$watch('model', function(val){
212 | if (val == false || val == undefined)
213 | return;
214 | else
215 | scope.dimmer_class = 'ui page active dimmer';
216 | });
217 | }
218 | };
219 | });
220 |
221 | 'use strict';
222 |
223 | angular.module('angularify.semantic.dropdown', [])
224 | .controller('DropDownController', ['$scope',
225 | function($scope) {
226 | $scope.options = [];
227 |
228 | this.add_option = function(title, value){
229 | $scope.options.push({'title': title, 'value': value});
230 | if (value == $scope.model){
231 | this.update_title(value)
232 | };
233 | };
234 |
235 | this.remove_option = function(title, value){
236 | for (var index in $scope.options)
237 | if ($scope.options[index].value == value &&
238 | $scope.options[index].title == title){
239 |
240 | $scope.options.splice(index, 1);
241 | // Remove only one item
242 | break;
243 | };
244 | };
245 |
246 | this.update_model = function (title, value) {
247 | if ($scope.model !== value)
248 | $scope.model = value;
249 | };
250 |
251 | this.update_title = function (value) {
252 | var changed = false;
253 |
254 | for (var index in $scope.options)
255 | if ($scope.options[index].value == value){
256 | $scope.title = $scope.options[index].title;
257 | changed = true;
258 | }
259 |
260 | if (changed){
261 | $scope.text_class = 'text';
262 | } else{
263 | $scope.title = $scope.original_title;
264 | $scope.text_class = 'default text';
265 | }
266 | };
267 |
268 | }
269 | ])
270 |
271 | .directive('dropdown', function() {
272 | return {
273 | restrict: 'E',
274 | replace: true,
275 | transclude: true,
276 | controller: 'DropDownController',
277 | scope: {
278 | title: '@',
279 | open: '@',
280 | model: '=ngModel'
281 | },
282 | template: '' +
283 | '
{{ title }}
' +
284 | '
' +
285 | '' +
287 | '
',
288 | link: function(scope, element, attrs, DropDownController) {
289 | scope.dropdown_class = 'ui selection dropdown';
290 | scope.menu_class = 'menu transition hidden';
291 | scope.text_class = 'default text';
292 | scope.original_title = scope.title;
293 |
294 | if (scope.open === 'true') {
295 | scope.is_open = true;
296 | scope.dropdown_class = scope.dropdown_class + ' active visible';
297 | scope.menu_class = scope.menu_class + ' visible';
298 | } else {
299 | scope.is_open = false;
300 | }
301 |
302 | /*
303 | * Watch for ng-model changing
304 | */
305 | scope.element = element;
306 | scope.$watch('model', function (value) {
307 | // update title or reset the original title if its empty
308 | DropDownController.update_title(value);
309 | });
310 |
311 | /*
312 | * Click handler
313 | */
314 | element.bind('click', function() {
315 | if (scope.is_open === false) {
316 | scope.$apply(function() {
317 | scope.dropdown_class = 'ui selection dropdown active visible';
318 | scope.menu_class = 'menu transition visible';
319 | });
320 | } else {
321 | scope.$apply(function() {
322 | scope.dropdown_class = 'ui selection dropdown';
323 | scope.menu_class = 'menu transition hidden';
324 | });
325 | }
326 | scope.is_open = !scope.is_open;
327 | });
328 | }
329 | };
330 | })
331 |
332 | .directive('dropdownGroup', function() {
333 | return {
334 | restrict: 'AE',
335 | replace: true,
336 | transclude: true,
337 | require: '^dropdown',
338 | scope: {
339 | title: '=title',
340 | value: '=value'
341 | },
342 | template: '{{ item_title }}
',
343 | link: function(scope, element, attrs, DropDownController) {
344 |
345 | // Check if title= was set... if not take the contents of the dropdown-group tag
346 | // title= is for dynamic variables from something like ng-repeat {{variable}}
347 | if (scope.title === undefined) {
348 | scope.item_title = attrs.title || element.children()[0].innerHTML;
349 | } else {
350 | scope.item_title = scope.title;
351 | }
352 | if (scope.value === undefined) {
353 | scope.item_value = attrs.value || scope.item_title;
354 | } else {
355 | scope.item_value = scope.value;
356 | }
357 |
358 | // Keep this option
359 | DropDownController.add_option(scope.item_title, scope.item_value);
360 |
361 | //
362 | // Menu item click handler
363 | //
364 | element.bind('click', function() {
365 | DropDownController.update_model(scope.item_title, scope.item_value);
366 | });
367 |
368 | scope.$on('$destroy', function(){
369 | DropDownController.remove_option(scope.item_title, scope.item_value);
370 | });
371 |
372 | }
373 | };
374 | });
375 | 'use strict';
376 |
377 | angular.module('angularify.semantic.modal', [])
378 |
379 | .directive('modal', function () {
380 | return {
381 | restrict: 'E',
382 | replace: true,
383 | transclude: true,
384 | require: 'ngModel',
385 | template: '
',
386 | link: function (scope, element, attrs, ngModel) {
387 | element.modal({
388 | onHide: function () {
389 | ngModel.$setViewValue(false);
390 | }
391 | });
392 | scope.$watch(function () {
393 | return ngModel.$modelValue;
394 | }, function (modelValue){
395 | element.modal(modelValue ? 'show' : 'hide');
396 | });
397 | }
398 | }
399 | });
400 |
401 | 'use strict';
402 |
403 | angular.module('angularify.semantic.popup', [])
404 |
405 | .directive('popup', function ($document) {
406 | return {
407 | restrict: "A",
408 | scope : {
409 | popup : "@"
410 | },
411 | link: function(scope, element, attrs) {
412 | var class_name = '';
413 | // convert to json
414 | var popup_meta_data = eval('(' + scope.popup + ')');
415 |
416 | var title = popup_meta_data['title'];
417 | if (title == undefined)
418 | title = '';
419 |
420 | var content = popup_meta_data['content'];
421 | if (content == undefined)
422 | content = '';
423 |
424 | var position = popup_meta_data['position'];
425 | if (position == undefined)
426 | position = 'top';
427 |
428 | var size = popup_meta_data['size'];
429 | if (size == undefined)
430 | size = 'small';
431 |
432 | if (position == 'left') {
433 | class_name = 'ui popup left center transition visible ' + size;
434 | } else if (position == 'right') {
435 | class_name = 'ui popup right center transition visible ' + size;
436 | } else if (position == 'bottom') {
437 | class_name = 'ui popup bottom center transition visible ' + size;
438 | } else {
439 | class_name = 'ui popup top center transition visible ' + size;
440 | }
441 |
442 | //
443 | // Get element X/Y of left corner
444 | //
445 | function getPos(ele){
446 | var x = 0;
447 | var y = 0;
448 | while(true){
449 | x += ele.offsetLeft;
450 | y += ele.offsetTop;
451 | if(ele.offsetParent === null)
452 | break;
453 | ele = ele.offsetParent;
454 | }
455 | return [x, y];
456 | }
457 |
458 | var current_element_position_top_left = getPos(element[0]);
459 | var current_element_height = element[0].offsetHeight;
460 | var current_element_width = element[0].offsetWidth;
461 |
462 | //
463 | // Remove element by class name
464 | //
465 | NodeList.prototype.remove = HTMLCollection.prototype.remove = function() {
466 | for(var i = 0, len = this.length; i < len; i++) {
467 | if(this[i] && this[i].parentElement) {
468 | this[i].parentElement.removeChild(this[i]);
469 | }
470 | }
471 | }
472 |
473 | //
474 | // Handle mouse over
475 | //
476 | element.bind('mouseenter', function(){
477 | var html = '';
478 |
479 | angular.element(element[0]).append(html);
480 |
481 | var popupHeight = document.getElementById('my-popup').clientHeight;
482 | var popupWidth = document.getElementById('my-popup').clientWidth;
483 |
484 | if (position == 'left') {
485 | document.getElementById('my-popup').style.top = current_element_position_top_left[1] + (current_element_height / 2) - (popupHeight / 2) + 'px';
486 | document.getElementById('my-popup').style.right = 'auto';
487 | document.getElementById('my-popup').style.left = current_element_position_top_left[0] - popupWidth - 10 + 'px';
488 | document.getElementById('my-popup').style.bottom = 'auto';
489 | document.getElementById('my-popup').style.display = 'inline-block';
490 | } else if (position == 'right') {
491 | document.getElementById('my-popup').style.top = current_element_position_top_left[1] + (current_element_height / 2) - (popupHeight / 2) + 'px';
492 | document.getElementById('my-popup').style.right = 'auto';
493 | document.getElementById('my-popup').style.left = current_element_position_top_left[0] + current_element_width + 'px';
494 | document.getElementById('my-popup').style.bottom = 'auto';
495 | document.getElementById('my-popup').style.display = 'inline-block';
496 | } else if (position == 'bottom') {
497 | document.getElementById('my-popup').style.top = current_element_position_top_left[1] + current_element_height + 'px';
498 | document.getElementById('my-popup').style.left = current_element_position_top_left[0] + (current_element_width / 2) - (popupWidth / 2) + 15 + 'px';
499 | document.getElementById('my-popup').style.right = 'auto';
500 | document.getElementById('my-popup').style.bottom = 'auto';
501 | document.getElementById('my-popup').style.display = 'inline-block';
502 | } else {
503 | document.getElementById('my-popup').style.top = current_element_position_top_left[1] - popupHeight - 10 + 'px';
504 | document.getElementById('my-popup').style.left = current_element_position_top_left[0] + (current_element_width / 2) - (popupWidth / 2) + 18 + 'px';
505 | document.getElementById('my-popup').style.right = 'auto';
506 | document.getElementById('my-popup').style.bottom = 'auto';
507 | document.getElementById('my-popup').style.display = 'inline-block';
508 | }
509 | });
510 |
511 | //
512 | // Handle mouse leave
513 | //
514 | element.bind('mouseleave', function(){
515 | document.getElementsByClassName("ui popup bottom center transition visible").remove();
516 | if (document.getElementById('my-popup') !== null)
517 | document.getElementById('my-popup').remove();
518 | });
519 | }
520 | }
521 | });
522 | 'use strict';
523 |
524 | angular
525 | .module('angularify.semantic.sidebar', [])
526 | .directive('sidebar', sidebar)
527 | .directive('sidebarLink', sidebarLink)
528 | .directive('sidebarItem', sidebarItem)
529 | .directive('sidebarItemGroup', sidebarItemGroup);
530 |
531 | function sidebar() {
532 | return {
533 | restrict: 'E',
534 | replace: true,
535 | transclude: true,
536 | template: '',
538 | scope: {
539 | buttonClass: '@'
540 | },
541 | link: function (scope, element, attrs) {
542 | element.sidebar('attach events', scope.buttonClass, 'show');
543 | }
544 | };
545 | }
546 |
547 | function sidebarItemGroup() {
548 | return {
549 | restrict: 'E',
550 | replace: true,
551 | transclude: true,
552 | template: '' +
553 | '' +
554 | '' +
555 | '
',
556 | scope: {
557 | title: '@'
558 | }
559 | };
560 | }
561 |
562 | function sidebarItem() {
563 | return {
564 | restrict: 'E',
565 | replace: true,
566 | transclude: true,
567 | template: '
'
568 | };
569 | }
570 |
571 | function sidebarLink() {
572 | return {
573 | restrict: 'E',
574 | replace: true,
575 | template: '' +
576 | ' ' +
577 | '{{ title }}' +
578 | ' ',
579 | scope: {
580 | title: '@',
581 | icon: '@',
582 | href: '@'
583 | }
584 | };
585 | }
586 | 'use strict';
587 |
588 | angular.module('angularify.semantic.rating', [])
589 |
590 | .directive('rating', function(){
591 | return {
592 | restrict: "E",
593 | replace: true,
594 | transclude: true,
595 | scope: {
596 | id: "@",
597 | size: "@",
598 | type: "@",
599 | model : '=ngModel'
600 | },
601 | template: '' +
602 | ' ' +
603 | ' ' +
604 | ' ' +
605 | ' ' +
606 | ' ' +
607 | '
',
608 | link: function(scope, element, attrs){
609 | if (scope.model == undefined)
610 | scope.model = 0;
611 |
612 | if (scope.model < 1 && scope.model > 5)
613 | scope.model = 0;
614 |
615 | // is rating already checked
616 | var checked = false;
617 |
618 | //
619 | // Set up icon type
620 | //
621 | if (scope.type == undefined)
622 | scope.type = 'star';
623 |
624 | //
625 | // Set up size
626 | //
627 | if (scope.size == undefined)
628 | scope.div_class = 'ui rating ' + scope.type;
629 | else if (scope.size == 'small')
630 | scope.div_class = 'ui small ' + scope.type + ' rating';
631 | else if (scope.size == 'large')
632 | scope.div_class = 'ui large ' + scope.type + ' rating';
633 | else if (scope.size == 'huge')
634 | scope.div_class = 'ui huge ' + scope.type + ' rating';
635 |
636 | //
637 | // set up icon class
638 | //
639 | scope.icon_class = 'icon';
640 |
641 | //
642 | // Handle mouse enter
643 | //
644 | scope.mouse_enter = function(icon_index){
645 | if (checked == true)
646 | return;
647 |
648 | var i = 1;
649 | for (i; i <= icon_index; i++){
650 | document.getElementById(scope.id + i).className = 'icon active';
651 | }
652 |
653 | return;
654 | };
655 |
656 | //
657 | // Handle mouse leave
658 | //
659 | scope.mouse_leave = function(icon_index){
660 | if (checked == true)
661 | return;
662 |
663 | var i = 1;
664 | for (i; i <= 5; i++){
665 | document.getElementById(scope.id + i).className = 'icon';
666 | }
667 |
668 | return;
669 | };
670 |
671 | //
672 | // Handle click
673 | //
674 | scope.click = function(icon_index, mode){
675 | var i = 1;
676 | for (i; i <= icon_index; i++){
677 | document.getElementById(scope.id + i).className = 'icon active';
678 | }
679 |
680 | if (icon_index !== 0)
681 | checked = true;
682 |
683 | return;
684 | };
685 |
686 | //
687 | // Watch for model
688 | //
689 | scope.$watch('model', function(val){
690 | scope.click(val);
691 | });
692 | }
693 | };
694 | });
695 |
696 | /* globals _:false */
697 | 'use strict';
698 | angular.module('angularify.semantic.wizard', [])
699 |
700 | .controller('WizardController', ['$scope',
701 | function($scope) {
702 | $scope.steps = [];
703 | $scope.currentStep = null;
704 | $scope.stepsLength = '';
705 |
706 | $scope.$watch('currentStep', function (step) {
707 | if (!step) return;
708 | var stepTitle = $scope.selectedStep.title;
709 | if ($scope.selectedStep && stepTitle !== $scope.currentStep) {
710 | $scope.goTo($scope.steps.filter(function (step) {
711 | return step.title ==- $scope.currentStep;
712 | })[0]);
713 | }
714 | });
715 |
716 | $scope.$watch('[editMode, steps.length]', function () {
717 | var editMode = $scope.editMode;
718 | if (editMode === undefined || editMode === null) return;
719 |
720 | if (editMode) {
721 | $scope.steps.forEach(function (step) {
722 | step.completed = true;
723 | });
724 | }
725 | }, true);
726 |
727 | this.addStep = function (step) {
728 | $scope.steps.push(step);
729 | if ($scope.steps.length === 1) {
730 | $scope.goTo($scope.steps[0]);
731 | }
732 | };
733 |
734 | $scope.goTo = function (step) {
735 | unselectAll();
736 | $scope.selectedStep = step;
737 |
738 | if ($scope.currentStep !== undefined) {
739 | $scope.currentStep = step.title;
740 | }
741 |
742 | step.selected = true;
743 | $scope.$emit('wizard:stepChanged', {
744 | step: step,
745 | index: $scope.steps.indexOf(step)
746 | });
747 | };
748 |
749 | function unselectAll() {
750 | $scope.steps.forEach(function (step) {
751 | step.selected = false;
752 | });
753 | $scope.selectedStep = null;
754 | }
755 |
756 | this.next = function () {
757 | var index = $scope.steps.indexOf($scope.selectedStep);
758 | $scope.selectedStep.completed = true;
759 | if (index === $scope.steps.length - 1) {
760 | this.finish();
761 | } else {
762 | $scope.goTo($scope.steps[index + 1]);
763 | }
764 | };
765 |
766 | this.goTo = function (step) {
767 | var stepTo;
768 |
769 | if (angular.isNumber(step)) {
770 | stepTo = $scope.steps[step];
771 | } else {
772 | stepTo = $scope.steps.filter(function (step) {
773 | return step.title === step;
774 | })[0];
775 | }
776 | $scope.goTo(stepTo);
777 | };
778 |
779 | this.finish = function() {
780 | if ($scope.onFinish) {
781 | $scope.selectedStep.completed = true;
782 | $scope.onFinish();
783 | }
784 | };
785 |
786 | this.cancel = this.previous = function() {
787 | var index = $scope.steps.indexOf($scope.selectedStep);
788 | if (index === 0) {
789 | throw new Error('Cant go back. Its already in step 0');
790 | } else {
791 | $scope.goTo($scope.steps[index - 1]);
792 | }
793 | };
794 |
795 | $scope.getStatus = function (step) {
796 | var statusClass = [];
797 |
798 | if (step.selected)
799 | statusClass.push('active');
800 | if (!step.selected && !step.completed)
801 | statusClass.push('disabled');
802 | if (step.completed)
803 | statusClass.push('completed');
804 |
805 | return statusClass;
806 | };
807 | }
808 | ])
809 | .directive('wizard', function() {
810 | return {
811 | restrict: 'EA',
812 | replace: true,
813 | transclude: true,
814 | scope: {
815 | fullwidth: "@",
816 | currentStep: '=?',
817 | onFinish: '&',
818 | editMode: '=',
819 | name: '@'
820 | },
821 | controller: 'WizardController',
822 | template: '' +
823 | '
' +
824 | '
' +
825 | '{{step.title}}' +
826 | '
' +
827 | '
' +
828 | '
' +
829 | '
' +
830 | '
',
831 | link: function(scope, element, attrs, WizardController) {
832 | if (scope.fullwidth === 'true') {
833 | var widthmatrix = {
834 | 0: '',
835 | 1: 'one',
836 | 2: 'two',
837 | 3: 'three',
838 | 4: 'four',
839 | 5: 'five',
840 | 6: 'six',
841 | 7: 'seven',
842 | 8: 'eight',
843 | 9: 'nine',
844 | 10: 'ten'
845 | };
846 | scope.stepsLength = widthmatrix[scope.steps.length];
847 | }
848 |
849 | }
850 | };
851 | })
852 | .directive('wizardPane', function() {
853 | return {
854 | restrict: 'EA',
855 | replace: true,
856 | transclude: true,
857 | require: '^wizard',
858 | controller: 'WizardController',
859 | scope: {
860 | title: '@'
861 | },
862 | template: '
',
863 | link: function(scope, element, attrs, WizardController) {
864 | WizardController.addStep(scope);
865 | }
866 | };
867 | });
868 |
869 | function wizardButtonDirective(action) {
870 | angular.module('angularify.semantic.wizard')
871 | .directive(action, function () {
872 | return {
873 | restrict: 'A',
874 | replace: false,
875 | require: '^wizard',
876 | link: function ($scope, $element, $attrs, wizard) {
877 | $scope.noMargin = { margin: 0 };
878 | $element.on('click', function (e) {
879 | e.preventDefault();
880 | $scope.$apply(function () {
881 | $scope.$eval($attrs[action]);
882 | wizard[action.replace('wz', '').toLowerCase()]();
883 | });
884 | });
885 | }
886 | };
887 | });
888 | }
889 |
890 | wizardButtonDirective('wzNext');
891 | wizardButtonDirective('wzPrevious');
892 | wizardButtonDirective('wzFinish');
893 | wizardButtonDirective('wzCancel');
894 |
--------------------------------------------------------------------------------
/dist/angular-semantic-ui.min.js:
--------------------------------------------------------------------------------
1 | function sidebar(){return{restrict:"E",replace:!0,transclude:!0,template:'',scope:{buttonClass:"@"},link:function(a,b,c){b.sidebar("attach events",a.buttonClass,"show")}}}function sidebarItemGroup(){return{restrict:"E",replace:!0,transclude:!0,template:'
',scope:{title:"@"}}}function sidebarItem(){return{restrict:"E",replace:!0,transclude:!0,template:'
'}}function sidebarLink(){return{restrict:"E",replace:!0,template:' {{ title }} ',scope:{title:"@",icon:"@",href:"@"}}}function wizardButtonDirective(a){angular.module("angularify.semantic.wizard").directive(a,function(){return{restrict:"A",replace:!1,require:"^wizard",link:function(b,c,d,e){b.noMargin={margin:0},c.on("click",function(c){c.preventDefault(),b.$apply(function(){b.$eval(d[a]),e[a.replace("wz","").toLowerCase()]()})})}}})}angular.module("angularify.semantic",["angularify.semantic.accordion","angularify.semantic.checkbox","angularify.semantic.dimmer","angularify.semantic.dropdown","angularify.semantic.modal","angularify.semantic.popup","angularify.semantic.rating","angularify.semantic.sidebar","angularify.semantic.wizard"]),angular.module("angularify.semantic.accordion",[]).controller("AccordionController",["$scope",function(a){a.accordions=[],this.add_accordion=function(b){a.accordions.push(b);var c=this;return b.$on("$destroy",function(a){c.remove_accordion(b)}),a.accordions},this.closeAll=function(b){var c=0,d=!1,e=a.accordions.indexOf(b);for(c in a.accordions)a.accordions[c].close&&(d=!0);if(1==d){for(c in a.accordions)c!==e&&(a.accordions[c].active=!1);return!0}return!1},this.remove_accordion=function(b){var c=a.accordions.indexOf(b);-1!==c&&a.accordions.splice(c,1)},this.is_close_all=function(){var b=0;for(b in a.accordions)if("true"==a.accordions[b].close)return!0;return!1}}]).directive("accordion",function(){return{restrict:"E",replace:!0,transclude:!0,controller:"AccordionController",scope:{close:"@"},template:'
',link:function(a,b,c,d){"undefined"!=typeof c.styled&&b.addClass("styled"),d.add_accordion(a)}}}).directive("accordionGroup",function(){return{restrict:"E",replace:!0,transclude:!0,scope:{title:"@",open:"@"},require:"^accordion",template:'',link:function(a,b,c,d){a.active="true"===c.open,d.add_accordion(a),a.click_on_accordion_tab=function(){d.closeAll(a),a.active=!a.active,b.children().last().slideToggle()}}}}),angular.module("angularify.semantic.checkbox",[]).directive("checkbox",function(){return{restrict:"E",replace:!0,transclude:!0,scope:{checked:"&?",disabled:"&?",ngModel:"=ngModel"},controller:function(){var a=this;angular.isFunction(a.checked)&&(a.ngModel=!!a.checked()),a.toggle=function(){angular.isFunction(a.disabled)&&a.disabled()||(a.ngModel=!a.ngModel)}},controllerAs:"vm",bindToController:!0,require:"ngModel",template:'
',link:function(){}}}),angular.module("angularify.semantic.dimmer",[]).directive("pageDimmer",function(){return{restrict:"E",replace:!0,transclude:!0,scope:{show:"=?",model:"=ngModel"},template:'',link:function(a,b,c,d){1==a.show?a.dimmer_class="ui page active dimmer":(a.show=!1,a.dimmer_class="ui page disable dimmer"),a.click_on_dimmer=function(){a.model=!1,a.dimmer_class="ui page dimmer"},a.$watch("model",function(b){0!=b&&void 0!=b&&(a.dimmer_class="ui page active dimmer")})}}}),angular.module("angularify.semantic.dropdown",[]).controller("DropDownController",["$scope",function(a){a.options=[],this.add_option=function(b,c){a.options.push({title:b,value:c}),c==a.model&&this.update_title(c)},this.remove_option=function(b,c){for(var d in a.options)if(a.options[d].value==c&&a.options[d].title==b){a.options.splice(d,1);break}},this.update_model=function(b,c){a.model!==c&&(a.model=c)},this.update_title=function(b){var c=!1;for(var d in a.options)a.options[d].value==b&&(a.title=a.options[d].title,c=!0);c?a.text_class="text":(a.title=a.original_title,a.text_class="default text")}}]).directive("dropdown",function(){return{restrict:"E",replace:!0,transclude:!0,controller:"DropDownController",scope:{title:"@",open:"@",model:"=ngModel"},template:'',link:function(a,b,c,d){a.dropdown_class="ui selection dropdown",a.menu_class="menu transition hidden",a.text_class="default text",a.original_title=a.title,"true"===a.open?(a.is_open=!0,a.dropdown_class=a.dropdown_class+" active visible",a.menu_class=a.menu_class+" visible"):a.is_open=!1,a.element=b,a.$watch("model",function(a){d.update_title(a)}),b.bind("click",function(){a.is_open===!1?a.$apply(function(){a.dropdown_class="ui selection dropdown active visible",a.menu_class="menu transition visible"}):a.$apply(function(){a.dropdown_class="ui selection dropdown",a.menu_class="menu transition hidden"}),a.is_open=!a.is_open})}}}).directive("dropdownGroup",function(){return{restrict:"AE",replace:!0,transclude:!0,require:"^dropdown",scope:{title:"=title",value:"=value"},template:'{{ item_title }}
',link:function(a,b,c,d){void 0===a.title?a.item_title=c.title||b.children()[0].innerHTML:a.item_title=a.title,void 0===a.value?a.item_value=c.value||a.item_title:a.item_value=a.value,d.add_option(a.item_title,a.item_value),b.bind("click",function(){d.update_model(a.item_title,a.item_value)}),a.$on("$destroy",function(){d.remove_option(a.item_title,a.item_value)})}}}),angular.module("angularify.semantic.modal",[]).directive("modal",function(){return{restrict:"E",replace:!0,transclude:!0,require:"ngModel",template:'
',link:function(a,b,c,d){b.modal({onHide:function(){d.$setViewValue(!1)}}),a.$watch(function(){return d.$modelValue},function(a){b.modal(a?"show":"hide")})}}}),angular.module("angularify.semantic.popup",[]).directive("popup",function($document){return{restrict:"A",scope:{popup:"@"},link:function(scope,element,attrs){function getPos(a){for(var b=0,c=0;;){if(b+=a.offsetLeft,c+=a.offsetTop,null===a.offsetParent)break;a=a.offsetParent}return[b,c]}var class_name="",popup_meta_data=eval("("+scope.popup+")"),title=popup_meta_data.title;void 0==title&&(title="");var content=popup_meta_data.content;void 0==content&&(content="");var position=popup_meta_data.position;void 0==position&&(position="top");var size=popup_meta_data.size;void 0==size&&(size="small"),class_name="left"==position?"ui popup left center transition visible "+size:"right"==position?"ui popup right center transition visible "+size:"bottom"==position?"ui popup bottom center transition visible "+size:"ui popup top center transition visible "+size;var current_element_position_top_left=getPos(element[0]),current_element_height=element[0].offsetHeight,current_element_width=element[0].offsetWidth;NodeList.prototype.remove=HTMLCollection.prototype.remove=function(){for(var a=0,b=this.length;b>a;a++)this[a]&&this[a].parentElement&&this[a].parentElement.removeChild(this[a])},element.bind("mouseenter",function(){var a='";angular.element(element[0]).append(a);var b=document.getElementById("my-popup").clientHeight,c=document.getElementById("my-popup").clientWidth;"left"==position?(document.getElementById("my-popup").style.top=current_element_position_top_left[1]+current_element_height/2-b/2+"px",document.getElementById("my-popup").style.right="auto",document.getElementById("my-popup").style.left=current_element_position_top_left[0]-c-10+"px",document.getElementById("my-popup").style.bottom="auto",document.getElementById("my-popup").style.display="inline-block"):"right"==position?(document.getElementById("my-popup").style.top=current_element_position_top_left[1]+current_element_height/2-b/2+"px",document.getElementById("my-popup").style.right="auto",document.getElementById("my-popup").style.left=current_element_position_top_left[0]+current_element_width+"px",document.getElementById("my-popup").style.bottom="auto",document.getElementById("my-popup").style.display="inline-block"):"bottom"==position?(document.getElementById("my-popup").style.top=current_element_position_top_left[1]+current_element_height+"px",document.getElementById("my-popup").style.left=current_element_position_top_left[0]+current_element_width/2-c/2+15+"px",document.getElementById("my-popup").style.right="auto",document.getElementById("my-popup").style.bottom="auto",document.getElementById("my-popup").style.display="inline-block"):(document.getElementById("my-popup").style.top=current_element_position_top_left[1]-b-10+"px",document.getElementById("my-popup").style.left=current_element_position_top_left[0]+current_element_width/2-c/2+18+"px",document.getElementById("my-popup").style.right="auto",document.getElementById("my-popup").style.bottom="auto",document.getElementById("my-popup").style.display="inline-block")}),element.bind("mouseleave",function(){document.getElementsByClassName("ui popup bottom center transition visible").remove(),null!==document.getElementById("my-popup")&&document.getElementById("my-popup").remove()})}}}),angular.module("angularify.semantic.sidebar",[]).directive("sidebar",sidebar).directive("sidebarLink",sidebarLink).directive("sidebarItem",sidebarItem).directive("sidebarItemGroup",sidebarItemGroup),angular.module("angularify.semantic.rating",[]).directive("rating",function(){return{restrict:"E",replace:!0,transclude:!0,scope:{id:"@",size:"@",type:"@",model:"=ngModel"},template:'
',link:function(a,b,c){void 0==a.model&&(a.model=0),a.model<1&&a.model>5&&(a.model=0);var d=!1;void 0==a.type&&(a.type="star"),void 0==a.size?a.div_class="ui rating "+a.type:"small"==a.size?a.div_class="ui small "+a.type+" rating":"large"==a.size?a.div_class="ui large "+a.type+" rating":"huge"==a.size&&(a.div_class="ui huge "+a.type+" rating"),a.icon_class="icon",a.mouse_enter=function(b){if(1!=d){var c=1;for(c;b>=c;c++)document.getElementById(a.id+c).className="icon active"}},a.mouse_leave=function(b){if(1!=d){var c=1;for(c;5>=c;c++)document.getElementById(a.id+c).className="icon"}},a.click=function(b,c){var e=1;for(e;b>=e;e++)document.getElementById(a.id+e).className="icon active";0!==b&&(d=!0)},a.$watch("model",function(b){a.click(b)})}}}),angular.module("angularify.semantic.wizard",[]).controller("WizardController",["$scope",function(a){function b(){a.steps.forEach(function(a){a.selected=!1}),a.selectedStep=null}a.steps=[],a.currentStep=null,a.stepsLength="",a.$watch("currentStep",function(b){if(b){var c=a.selectedStep.title;a.selectedStep&&c!==a.currentStep&&a.goTo(a.steps.filter(function(b){return b.title==-a.currentStep})[0])}}),a.$watch("[editMode, steps.length]",function(){var b=a.editMode;void 0!==b&&null!==b&&b&&a.steps.forEach(function(a){a.completed=!0})},!0),this.addStep=function(b){a.steps.push(b),1===a.steps.length&&a.goTo(a.steps[0])},a.goTo=function(c){b(),a.selectedStep=c,void 0!==a.currentStep&&(a.currentStep=c.title),c.selected=!0,a.$emit("wizard:stepChanged",{step:c,index:a.steps.indexOf(c)})},this.next=function(){var b=a.steps.indexOf(a.selectedStep);a.selectedStep.completed=!0,b===a.steps.length-1?this.finish():a.goTo(a.steps[b+1])},this.goTo=function(b){var c;c=angular.isNumber(b)?a.steps[b]:a.steps.filter(function(a){return a.title===a})[0],a.goTo(c)},this.finish=function(){a.onFinish&&(a.selectedStep.completed=!0,a.onFinish())},this.cancel=this.previous=function(){var b=a.steps.indexOf(a.selectedStep);if(0===b)throw new Error("Cant go back. Its already in step 0");a.goTo(a.steps[b-1])},a.getStatus=function(a){var b=[];return a.selected&&b.push("active"),a.selected||a.completed||b.push("disabled"),a.completed&&b.push("completed"),b}}]).directive("wizard",function(){return{restrict:"EA",replace:!0,transclude:!0,scope:{fullwidth:"@",currentStep:"=?",onFinish:"&",editMode:"=",name:"@"},controller:"WizardController",template:'',link:function(a,b,c,d){if("true"===a.fullwidth){var e={0:"",1:"one",2:"two",3:"three",4:"four",5:"five",6:"six",7:"seven",8:"eight",9:"nine",10:"ten"};a.stepsLength=e[a.steps.length]}}}}).directive("wizardPane",function(){return{restrict:"EA",replace:!0,transclude:!0,require:"^wizard",controller:"WizardController",scope:{title:"@"},template:'
',link:function(a,b,c,d){d.addStep(a)}}}),wizardButtonDirective("wzNext"),wizardButtonDirective("wzPrevious"),wizardButtonDirective("wzFinish"),wizardButtonDirective("wzCancel");
--------------------------------------------------------------------------------
/karma.conf.js:
--------------------------------------------------------------------------------
1 | basePath = '.';
2 |
3 | files = [
4 | JASMINE,
5 | JASMINE_ADAPTER,
6 | 'bower_components/jquery/dist/jquery.min.js',
7 | 'bower_components/angular/angular.min.js',
8 | 'bower_components/angular-mocks/angular-mocks.js',
9 | 'src/**/*.js',
10 | ];
11 |
12 | exclude = [
13 | 'src/**/docs/*', 'src/**/README.md'
14 | ];
15 |
16 | browsers = [
17 | 'PhantomJS'
18 | ];
19 |
20 | reporters = ['progress'];
21 |
22 | port = 9018;
23 | runnerPort = 9100;
24 |
25 | colors = true;
26 |
27 | logLevel = LOG_INFO
28 |
29 | autoWatch = false;
30 |
31 | singleRun = false;
32 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "angular-semantic-ui",
3 | "description": "Angular - AngularJS directives for Semantic UI.",
4 | "version": "0.0.3",
5 | "keywords": [
6 | "angular",
7 | "ui",
8 | "semantic"
9 | ],
10 | "homepage": "http://0xAX.github.io/angular-semantic-ui",
11 | "bugs": "https://github.com/angularify/angular-semantic-ui",
12 | "author": {
13 | "name": "Alex Kuleshov",
14 | "url": "https://github.com/0xAX"
15 | },
16 | "repository": {
17 | "type": "git",
18 | "url": "https://github.com/angularify/angular-semantic-ui.git"
19 | },
20 | "licenses": [
21 | {
22 | "type": "MIT",
23 | "url": "https://github.com/angularify/angular-semantic-ui/blob/master/LICENSE.md"
24 | }
25 | ],
26 | "dependencies": {},
27 | "devDependencies": {
28 | "grunt": "~0.4.1",
29 | "grunt-ngdocs": "~0.1.1",
30 | "grunt-conventional-changelog": "~0.1.2",
31 | "grunt-contrib-concat": "~0.3.0",
32 | "grunt-contrib-copy": "~0.5.0",
33 | "grunt-contrib-uglify": "~0.3.0",
34 | "grunt-contrib-watch": "~0.5.0",
35 | "grunt-contrib-jshint": "~0.8.0",
36 | "karma-phantomjs-launcher" : "latest",
37 | "grunt-html2js": "~0.2.0",
38 | "grunt-karma": "~0.4.4",
39 | "node-markdown": "0.1.1",
40 | "semver": "~2.2.0",
41 | "shelljs": "~0.2.0"
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/accordion/README.md:
--------------------------------------------------------------------------------
1 | angularify.semantic.accordion
2 | ===============================
3 |
4 | `angularify.semantic.accordion` - accordion directive for angular.js.
5 |
6 | Usage
7 | -------------------------------
8 |
9 | ```html
10 |
11 |
12 | Some text in first tab
13 |
14 |
15 | Some text in second tab
16 |
17 |
18 | ```
19 |
20 | `` - can have following attributes:
21 |
22 | * `close` - true || false, close all tabs if it is `true`.
23 |
24 | `` - can have following attributes:
25 |
26 | * `title` - tab's title;
27 | * `open` - `true` || `false`, current `accordion-group` will be open.
28 |
29 | Contribution
30 | -------------------------------
31 |
32 | 1. Fork main [repository](https://github.com/angularify/angular-semantic-ui).
33 | 2. Make changes.
34 | 3. Create issue.
35 | 4. Send pull request.
36 | 5. Thank you.
37 |
38 | TODO
39 | -------------------------------
40 |
41 | 1. Add transition.
42 | 2. Add basic accordion.
43 | 3. Add fluid-accordion.
44 | 3. More tests.
--------------------------------------------------------------------------------
/src/accordion/accordion.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | angular.module('angularify.semantic.accordion', [])
4 |
5 | .controller('AccordionController', ['$scope', function($scope){
6 | $scope.accordions = [];
7 |
8 | this.add_accordion = function(scope) {
9 | $scope.accordions.push(scope);
10 |
11 | var _this = this;
12 | scope.$on('$destroy', function (event) {
13 | _this.remove_accordion(scope);
14 | });
15 |
16 | return $scope.accordions;
17 | }
18 |
19 | this.closeAll = function(scope) {
20 | var i = 0;
21 | var isCloseAll = false;
22 |
23 | var index = $scope.accordions.indexOf(scope);
24 |
25 | for (i in $scope.accordions){
26 | if ($scope.accordions[i].close)
27 | isCloseAll = true;
28 | }
29 |
30 | if (isCloseAll == true){
31 | for (i in $scope.accordions){
32 | if (i !== index) {
33 | $scope.accordions[i].active = false;
34 | }
35 | }
36 |
37 | return true;
38 | }
39 |
40 | return false;
41 |
42 | }
43 |
44 | this.remove_accordion = function(scope) {
45 | var index = $scope.accordions.indexOf(scope);
46 | if ( index !== -1 ) {
47 | $scope.accordions.splice(index, 1);
48 | }
49 | }
50 |
51 | this.is_close_all = function() {
52 | var i = 0;
53 |
54 | for (i in $scope.accordions){
55 | if ($scope.accordions[i].close == 'true')
56 | return true;
57 | }
58 | return false;
59 | }
60 | }])
61 |
62 | .directive('accordion', function () {
63 | return {
64 | restrict: 'E',
65 | replace: true,
66 | transclude: true,
67 | controller: 'AccordionController',
68 | scope: {
69 | 'close': '@'
70 | },
71 | template: "
",
72 | link: function(scope, element, attrs, AccordionController) {
73 |
74 | if(typeof attrs.styled !== 'undefined') {
75 | element.addClass('styled');
76 | }
77 |
78 | AccordionController.add_accordion(scope);
79 | }
80 | }
81 | })
82 |
83 | .directive('accordionGroup', function() {
84 | return {
85 | restrict: 'E',
86 | replace: true,
87 | transclude: true,
88 | scope : {
89 | title: '@',
90 | open: '@'
91 | },
92 | require:'^accordion',
93 | template: "\
94 |
\
95 | \
96 | {{ title }} \
97 |
\
98 |
\
99 |
\
100 |
",
101 |
102 | link: function(scope, element, attrs, AccordionController) {
103 |
104 | // set up active
105 | scope.active = attrs.open === 'true';
106 |
107 | // Add the accordion to the controller
108 | AccordionController.add_accordion(scope);
109 |
110 | // Click handler
111 | scope.click_on_accordion_tab = function(){
112 |
113 | // class all first of all
114 | AccordionController.closeAll(scope);
115 |
116 | // Swap the active state
117 | scope.active = !scope.active;
118 |
119 | // Add animation to the accordion group content
120 | element.children().last().slideToggle();
121 | };
122 | }
123 | };
124 | });
--------------------------------------------------------------------------------
/src/accordion/docs/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/angularify/angular-semantic-ui/6ac38e0bc5c91b084fae8defecb9e3e9ed74c3a8/src/accordion/docs/.gitkeep
--------------------------------------------------------------------------------
/src/accordion/docs/controllers.js:
--------------------------------------------------------------------------------
1 | var App = angular.module('AccordionApp', ['angularify.semantic.accordion']);
2 |
3 | function RootCtrl ($scope) {
4 |
5 | }
--------------------------------------------------------------------------------
/src/accordion/docs/demo.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Semantic UI + Angular.JS
6 |
7 |
8 |
9 |
10 |
11 | Some text in first tab
12 |
13 |
14 | Some text in second tab
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/src/accordion/test/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/angularify/angular-semantic-ui/6ac38e0bc5c91b084fae8defecb9e3e9ed74c3a8/src/accordion/test/.gitkeep
--------------------------------------------------------------------------------
/src/accordion/test/accordion.spec.js:
--------------------------------------------------------------------------------
1 | describe('accordion', function () {
2 | var $scope;
3 |
4 | beforeEach(module('angularify.semantic.accordion'));
5 |
6 | beforeEach(inject(function ($rootScope) {
7 | $scope = $rootScope;
8 | }));
9 |
10 | describe('controller', function () {
11 | var ctrl, $element, $attrs;
12 |
13 | beforeEach(inject(function($controller) {
14 | $attrs = {}; $element = {};
15 | ctrl = $controller('AccordionController', { $scope: $scope });
16 | }));
17 |
18 | describe('add_accordion', function() {
19 | it("AccordionController add_accordion test", function(){
20 | var acc1, acc2;
21 | ctrl.add_accordion(acc1 = $scope.$new());
22 | ctrl.add_accordion(acc2 = $scope.$new());
23 | expect($scope.accordions.length).toBe(2);
24 | });
25 | });
26 |
27 | describe('remove_accordion', function(){
28 | it("AccordionController remove_accordion test", function(){
29 | var acc1, acc2;
30 | ctrl.add_accordion(acc1 = $scope.$new());
31 | ctrl.add_accordion(acc2 = $scope.$new());
32 | ctrl.remove_accordion(acc2);
33 | expect($scope.accordions.length).toBe(1);
34 | })
35 | });
36 | });
37 | });
--------------------------------------------------------------------------------
/src/angularify.semantic.js:
--------------------------------------------------------------------------------
1 | angular.module('angularify.semantic', ['angularify.semantic.accordion',
2 | 'angularify.semantic.checkbox',
3 | 'angularify.semantic.dimmer',
4 | 'angularify.semantic.dropdown',
5 | 'angularify.semantic.modal',
6 | 'angularify.semantic.popup',
7 | 'angularify.semantic.rating',
8 | 'angularify.semantic.sidebar',
9 | 'angularify.semantic.wizard']);
10 |
--------------------------------------------------------------------------------
/src/checkbox/README.md:
--------------------------------------------------------------------------------
1 | angularify.semantic.checkbox
2 | ===============================
3 |
4 | `angularify.semantic.checkbox` - checkbox directive for angular.js.
5 |
6 | Usage
7 | -------------------------------
8 |
9 | ```html
10 |
11 | Alex
12 |
13 | 0xAX
14 |
15 | User
16 |
17 | isActive
18 |
19 | ```
20 |
21 | `checkbox` - can have following properties:
22 |
23 | * `class / ng-class`: - `standard` || `slider` || `toggle` || `large` || `huge` || `undefined` - the style of checkbox;
24 | * `checked` - `true` || `false`, checked checkbox or not;
25 | - `disabled` - `disabled`, optional if the checkbox is disabled or not;
26 | * `ng-model` - angular model.
27 |
28 | Contribution
29 | -------------------------------
30 |
31 | 1. Fork main [repository](https://github.com/angularify/angular-semantic-ui).
32 | 2. Make changes.
33 | 3. Create issue.
34 | 4. Send pull request.
35 | 5. Thank you.
36 |
37 | TODO
38 | -------------------------------
39 |
40 | 1. Add radio-button.
41 |
--------------------------------------------------------------------------------
/src/checkbox/checkbox.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | angular.module('angularify.semantic.checkbox', [])
4 | .directive('checkbox', function() {
5 | return {
6 | restrict: 'E',
7 | replace: true,
8 | transclude: true,
9 | scope: {
10 | checked: '&?',
11 | disabled: '&?',
12 | ngModel: '=ngModel'
13 | },
14 | controller: function() {
15 | var vm = this;
16 |
17 | // TODO: assert this is usefull ?
18 | // if(angular.isUndefined(vm.ngModel)) { vm.ngModel = !!vm.ngModel; }
19 |
20 | if(angular.isFunction(vm.checked)) { vm.ngModel = !!vm.checked(); }
21 |
22 | vm.toggle = function() {
23 | if(angular.isFunction(vm.disabled) && vm.disabled()) return;
24 | vm.ngModel = !vm.ngModel;
25 | }
26 | },
27 | controllerAs: 'vm',
28 | bindToController: true,
29 | require: 'ngModel',
30 | template: '' +
31 | ' ' +
32 | ' ' +
33 | '
',
34 | link: function() { }
35 | };
36 | });
37 |
--------------------------------------------------------------------------------
/src/checkbox/docs/controllers.js:
--------------------------------------------------------------------------------
1 | var checkBoxApp = angular.module('checkBoxApp', ['angularify.semantic.checkbox']);
2 |
3 | checkBoxApp.controller('RootCtrl', function() { });
4 |
5 |
--------------------------------------------------------------------------------
/src/checkbox/docs/demo.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Semantic UI + Angular.JS
7 |
8 |
9 |
10 |
11 | Alex
12 |
13 | 0xAX
14 |
15 | User
16 |
17 | User
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/src/checkbox/test/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/angularify/angular-semantic-ui/6ac38e0bc5c91b084fae8defecb9e3e9ed74c3a8/src/checkbox/test/.gitkeep
--------------------------------------------------------------------------------
/src/checkbox/test/checkbox.spec.js:
--------------------------------------------------------------------------------
1 | describe('checkbox', function () {
2 | beforeEach(module('angularify.semantic.checkbox'));
3 |
4 | var $controller;
5 | var $compile;
6 | var $rootScope;
7 |
8 | beforeEach(inject(function(_$controller_, _$compile_, _$rootScope_) {
9 | $controller = _$controller_;
10 | $compile = _$compile_;
11 | $rootScope = _$rootScope_;
12 | }));
13 |
14 | describe('directive', function() {
15 | it('should require ng-model', function() {
16 | expect(function() {
17 | $compile('checkbox\'s label ')($rootScope)
18 | }).toThrow();
19 | });
20 |
21 | it('should compile when ng-model provided', function() {
22 | var element = $compile('checkbox\'s label ')($rootScope);
23 | $rootScope.$digest();
24 |
25 | expect(element.is('.ui.checkbox')).toBeTruthy()
26 |
27 | expect(element.children().length).toEqual(2);
28 | expect(angular.element(element.children()[0]).is('input:checkbox')).toBeTruthy();
29 | expect(element.children('input').is('input:checkbox')).toBeTruthy();
30 | expect(angular.element(element.children()[1]).is('label')).toBeTruthy();
31 |
32 | expect(element.children('label').text()).toEqual('checkbox\'s label');
33 | expect(element.find('input').is(':checked')).toBeFalsy();
34 | expect($rootScope.value).toBeFalsy();
35 |
36 | element.find('input').click();
37 | expect(element.find('input').is(':checked')).toBeTruthy();
38 | expect($rootScope.value).toBeTruthy();
39 | });
40 |
41 | it('should be checked when marked checked', function() {
42 | var element = $compile('checkbox\'s label ')($rootScope);
43 | $rootScope.$digest();
44 | expect(element.find('input').is(':checked')).toBeTruthy();
45 | expect($rootScope.value).toBeTruthy();
46 | });
47 |
48 | it('should be not checked when marked checked false', function() {
49 | var element = $compile('checkbox\'s label ')($rootScope);
50 | $rootScope.$digest();
51 | expect(element.find('input').is(':checked')).toBeFalsy();
52 | expect($rootScope.value).toBeFalsy();
53 | });
54 |
55 | it('should be disabled when marked disabled', function() {
56 | var element = $compile('checkbox\'s label ')($rootScope);
57 | $rootScope.$digest();
58 | expect(element.find('input').is(':disabled')).toBeTruthy();
59 |
60 | expect(element.find('input').is(':checked')).toBeFalsy();
61 | expect($rootScope.value).toBeFalsy();
62 | element.find('label').click();
63 | expect(element.find('input').is(':checked')).toBeFalsy();
64 | expect($rootScope.value).toBeFalsy();
65 | });
66 |
67 | it('should be enabled when marked disabled false', function() {
68 | var element = $compile('checkbox\'s label ')($rootScope);
69 | $rootScope.$digest();
70 | expect(element.find('input').is(':disabled')).toBeFalsy();
71 | });
72 |
73 | it('should be large when size is large', function() {
74 | var element = $compile('checkbox\'s label ')($rootScope);
75 | $rootScope.$digest();
76 | expect(element.is('.large')).toBeTruthy()
77 | });
78 |
79 | it('should be huge when size is huge', function() {
80 | var element = $compile('checkbox\'s label ')($rootScope);
81 | $rootScope.$digest();
82 | expect(element.is('.huge')).toBeTruthy()
83 | });
84 |
85 | it('should be slider when type is slider', function() {
86 | var element = $compile('checkbox\'s label ')($rootScope);
87 | $rootScope.$digest();
88 | expect(element.is('.slider')).toBeTruthy()
89 | });
90 |
91 | it('should be toggle when type is toggle', function() {
92 | var element = $compile('checkbox\'s label ')($rootScope);
93 | $rootScope.$digest();
94 | expect(element.is('.toggle')).toBeTruthy()
95 | });
96 |
97 | });
98 | });
99 |
--------------------------------------------------------------------------------
/src/dimmer/README.md:
--------------------------------------------------------------------------------
1 | angularify.semantic.dimmer
2 | ===============================
3 |
4 | `angularify.semantic.dimmer` - dimmer directive for angular.js.
5 |
6 | Usage
7 | -------------------------------
8 |
9 | ```html
10 |
13 |
14 |
15 | Open dimmer
16 |
17 | ```
18 |
19 | ```javascript
20 | var dimmerApp = angular.module('dimmerApp', ['angularify.semantic.dimmer']);
21 |
22 | function RootCtrl ($scope) {
23 | $scope.dimmer = function(){
24 | $scope.show_dimmer = true;
25 | }
26 | }
27 | ```
28 |
29 | `dimmer` - can have following attributes:
30 |
31 | * `ng-model` - angular model;
32 | * `show` - is current dimmer showed.
33 |
34 | Contribution
35 | -------------------------------
36 |
37 | 1. Fork main [repository](https://github.com/angularify/angular-semantic-ui).
38 | 2. Make changes.
39 | 3. Create issue.
40 | 4. Send pull request.
41 | 5. Thank you.
42 |
43 | TODO
44 | -------------------------------
45 |
46 | 1. add duration;
47 | 2. add animation;
48 | 3. add different dimmer types.
--------------------------------------------------------------------------------
/src/dimmer/dimmer.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | angular.module('angularify.semantic.dimmer', [])
4 |
5 | .directive("pageDimmer", function () {
6 | return {
7 | restrict: 'E',
8 | replace: true,
9 | transclude: true,
10 | scope : {
11 | show : "=?",
12 | model: '=ngModel'
13 | },
14 | template: "",
19 | link : function(scope, element, attrs, ngModel) {
20 |
21 | if (scope.show == true) {
22 | scope.dimmer_class = 'ui page active dimmer';
23 | }
24 | else {
25 | scope.show = false;
26 | scope.dimmer_class = 'ui page disable dimmer';
27 | }
28 |
29 | //
30 | // Click on dimmer handler
31 | //
32 | scope.click_on_dimmer = function(){
33 | scope.model = false;
34 | scope.dimmer_class = 'ui page dimmer';
35 | }
36 |
37 | //
38 | // Watch for the ng-model changing
39 | //
40 | scope.$watch('model', function(val){
41 | if (val == false || val == undefined)
42 | scope.dimmer_class = 'ui page dimmer';
43 | else
44 | scope.dimmer_class = 'ui page active dimmer';
45 | });
46 | }
47 | };
48 | });
49 |
--------------------------------------------------------------------------------
/src/dimmer/docs/controllers.js:
--------------------------------------------------------------------------------
1 | var dimmerApp = angular.module('dimmerApp', ['angularify.semantic.dimmer']);
2 | dimmerApp.controller('RootCtrl', RootCtrl);
3 |
4 | function RootCtrl($scope) {
5 | $scope.dimmer = function(){
6 | $scope.show_dimmer = true;
7 | };
8 | }
--------------------------------------------------------------------------------
/src/dimmer/docs/demo.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Semantic UI + Angular.JS
6 |
7 |
8 |
9 |
12 |
13 |
14 | Open dimmer
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/src/dimmer/test/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/angularify/angular-semantic-ui/6ac38e0bc5c91b084fae8defecb9e3e9ed74c3a8/src/dimmer/test/.gitkeep
--------------------------------------------------------------------------------
/src/dropdown/README.md:
--------------------------------------------------------------------------------
1 | angularify.semantic.dropdown
2 | ===============================
3 |
4 | `angularify.semantic.dropdown` - dropdown directive for angular.js.
5 |
6 | Usage
7 | -------------------------------
8 |
9 | ```html
10 |
11 | item1
12 | item2
13 | item3
14 | item4
15 |
16 | ```
17 |
18 | or
19 |
20 | ```html
21 |
22 | {{c.title}}
23 |
24 | ```
25 |
26 | `dropdown` - can have following attributes:
27 |
28 | * `title` - title(placeholder) of the dropdown;
29 | * `ng-model` - angular model;
30 | * `open` - `true` || `false`. is current dropdown opened.
31 |
32 | `dropdown-group` - can have following attributes:
33 |
34 | * `title` - optional setting to set the name and value (if value not specified) of the entry. Helpful for those {{variables}} that don't;
35 | * `value` - set item value.
36 |
37 | Contribution
38 | -------------------------------
39 |
40 | 1. Fork main [repository](https://github.com/angularify/angular-semantic-ui).
41 | 2. Make changes.
42 | 3. Create issue.
43 | 4. Send pull request.
44 | 5. Thank you.
45 |
46 | TODO
47 | -------------------------------
48 |
49 | 1. Add different dropdown types.
50 |
--------------------------------------------------------------------------------
/src/dropdown/docs/controllers.js:
--------------------------------------------------------------------------------
1 |
2 | angular
3 | .module('dropdownApp', ['angularify.semantic.dropdown'])
4 | .controller('RootCtrl', RootCtrl);
5 |
6 | function RootCtrl ($scope) {
7 | $scope.dropdown_model = 'item3';
8 |
9 | $scope.dropdown_repeat_model = 'item1';
10 | $scope.dropdown_items = [
11 | 'item1',
12 | 'item2',
13 | 'item3',
14 | 'item4'
15 | ];
16 |
17 | $scope.dropdown_key_value_model = '';
18 | $scope.dropdown_key_value_items = {
19 | 'item1': 'Cool item 1',
20 | 'item2': 'Cool item 2',
21 | 'item3': 'Cool item 3',
22 | 'item4': 'Cool item 4'
23 | };
24 |
25 |
26 | }
27 |
28 |
--------------------------------------------------------------------------------
/src/dropdown/docs/demo.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Semantic UI + Angular.JS
6 |
7 |
8 |
9 | Basic
10 |
11 |
12 | item1
13 | item2
14 | item3
15 | item4
16 |
17 |
18 |
19 | Current selection is: {{ dropdown_model }}
20 |
21 |
22 | With ng-repeat
23 |
24 |
25 | {{ item }}
26 |
27 |
28 |
29 | Current selection is: {{ dropdown_repeat_model }}
30 |
31 |
32 | With ng-repeat and key/value objects
33 |
34 |
35 | {{ title }}
36 |
37 |
38 |
39 | Current selection is: {{ dropdown_key_value_model }}
40 |
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/src/dropdown/dropdown.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | angular.module('angularify.semantic.dropdown', [])
4 | .controller('DropDownController', ['$scope',
5 | function($scope) {
6 | $scope.options = [];
7 |
8 | this.add_option = function(title, value){
9 | $scope.options.push({'title': title, 'value': value});
10 | if (value == $scope.model){
11 | this.update_title(value)
12 | };
13 | };
14 |
15 | this.remove_option = function(title, value){
16 | for (var index in $scope.options)
17 | if ($scope.options[index].value == value &&
18 | $scope.options[index].title == title){
19 |
20 | $scope.options.splice(index, 1);
21 | // Remove only one item
22 | break;
23 | };
24 | };
25 |
26 | this.update_model = function (title, value) {
27 | if ($scope.model !== value)
28 | $scope.model = value;
29 | };
30 |
31 | this.update_title = function (value) {
32 | var changed = false;
33 |
34 | for (var index in $scope.options)
35 | if ($scope.options[index].value == value){
36 | $scope.title = $scope.options[index].title;
37 | changed = true;
38 | }
39 |
40 | if (changed){
41 | $scope.text_class = 'text';
42 | } else{
43 | $scope.title = $scope.original_title;
44 | $scope.text_class = 'default text';
45 | }
46 | };
47 |
48 | }
49 | ])
50 |
51 | .directive('dropdown', function() {
52 | return {
53 | restrict: 'E',
54 | replace: true,
55 | transclude: true,
56 | controller: 'DropDownController',
57 | scope: {
58 | title: '@',
59 | open: '@',
60 | model: '=ngModel'
61 | },
62 | template: '' +
63 | '
{{ title }}
' +
64 | '
' +
65 | '' +
67 | '
',
68 | link: function(scope, element, attrs, DropDownController) {
69 | scope.dropdown_class = 'ui selection dropdown';
70 | scope.menu_class = 'menu transition hidden';
71 | scope.text_class = 'default text';
72 | scope.original_title = scope.title;
73 |
74 | if (scope.open === 'true') {
75 | scope.is_open = true;
76 | scope.dropdown_class = scope.dropdown_class + ' active visible';
77 | scope.menu_class = scope.menu_class + ' visible';
78 | } else {
79 | scope.is_open = false;
80 | }
81 |
82 | /*
83 | * Watch for ng-model changing
84 | */
85 | scope.element = element;
86 | scope.$watch('model', function (value) {
87 | // update title or reset the original title if its empty
88 | DropDownController.update_title(value);
89 | });
90 |
91 | /*
92 | * Click handler
93 | */
94 | element.bind('click', function() {
95 | if (scope.is_open === false) {
96 | scope.$apply(function() {
97 | scope.dropdown_class = 'ui selection dropdown active visible';
98 | scope.menu_class = 'menu transition visible';
99 | });
100 | } else {
101 | scope.$apply(function() {
102 | scope.dropdown_class = 'ui selection dropdown';
103 | scope.menu_class = 'menu transition hidden';
104 | });
105 | }
106 | scope.is_open = !scope.is_open;
107 | });
108 | }
109 | };
110 | })
111 |
112 | .directive('dropdownGroup', function() {
113 | return {
114 | restrict: 'AE',
115 | replace: true,
116 | transclude: true,
117 | require: '^dropdown',
118 | scope: {
119 | title: '=title',
120 | value: '=value'
121 | },
122 | template: '{{ item_title }}
',
123 | link: function(scope, element, attrs, DropDownController) {
124 |
125 | // Check if title= was set... if not take the contents of the dropdown-group tag
126 | // title= is for dynamic variables from something like ng-repeat {{variable}}
127 | if (scope.title === undefined) {
128 | scope.item_title = attrs.title || element.children()[0].innerHTML;
129 | } else {
130 | scope.item_title = scope.title;
131 | }
132 | if (scope.value === undefined) {
133 | scope.item_value = attrs.value || scope.item_title;
134 | } else {
135 | scope.item_value = scope.value;
136 | }
137 |
138 | // Keep this option
139 | DropDownController.add_option(scope.item_title, scope.item_value);
140 |
141 | //
142 | // Menu item click handler
143 | //
144 | element.bind('click', function() {
145 | DropDownController.update_model(scope.item_title, scope.item_value);
146 | });
147 |
148 | scope.$on('$destroy', function(){
149 | DropDownController.remove_option(scope.item_title, scope.item_value);
150 | });
151 |
152 | }
153 | };
154 | });
--------------------------------------------------------------------------------
/src/dropdown/test/dropdown.spec.js:
--------------------------------------------------------------------------------
1 | describe('dropdown', function () {
2 | var element, $scope;
3 |
4 | beforeEach(module('angularify.semantic.dropdown'));
5 |
6 | beforeEach(inject(function($rootScope, $compile) {
7 | element = angular.element(
8 | '' +
9 | '' +
10 | '' +
13 | '{{ title }}' +
14 | ' ' +
15 | ' ' +
16 | '
');
17 |
18 | scope = $rootScope;
19 | scope.dropdown_model = '';
20 | scope.dropdown_items = {};
21 | $compile(element)(scope);
22 | scope.$digest();
23 | }));
24 |
25 | it('should create element with default header', inject(function($compile, $rootScope) {
26 | var header = element.find('div.dropdown > div');
27 | expect(header.eq(0).text()).toBe('No value');
28 | }));
29 |
30 | it('should have right amount of options', inject(function($compile, $rootScope) {
31 | var items = element.find('.menu > div.item');
32 | expect(items.length).toBe(0);
33 |
34 | scope.$apply(function() {
35 | scope.dropdown_items = [{'item1': 'Cool item1'}, {'item2': 'Cool item2'}];
36 | });
37 |
38 | items = element.find('.menu > div.item');
39 | expect(items.length).toBe(2);
40 |
41 | }));
42 |
43 | it('should change model value when user choose option', inject(function($compile, $rootScope) {
44 | scope.$apply(function() {
45 | scope.dropdown_items = {'item1': 'Cool item1',
46 | 'item2': 'Cool item2'};
47 | });
48 |
49 | var dropdown = element.find('.dropdown');
50 | dropdown.click();
51 |
52 | var option1 = element.find('.menu > div.item').eq(0);
53 | option1.click()
54 | expect(scope.dropdown_model).toBe('item1');
55 |
56 | }));
57 |
58 | it('should change element header when user choose option', inject(function($compile, $rootScope) {
59 | scope.$apply(function() {
60 | scope.dropdown_items = {'item1': 'Cool item1',
61 | 'item2': 'Cool item2'};
62 | });
63 |
64 | var dropdown = element.find('.dropdown');
65 | dropdown.click();
66 |
67 | var option1 = element.find('.menu > div.item').eq(0);
68 | option1.click()
69 |
70 | var header = element.find('div.dropdown > div');
71 | expect(header.eq(0).text()).toBe('Cool item1');
72 |
73 | }));
74 |
75 | });
76 |
--------------------------------------------------------------------------------
/src/modal/README.md:
--------------------------------------------------------------------------------
1 | angularify.semantic.modal
2 | ===============================
3 |
4 | `angularify.semantic.modal` - modal window directive for angular.js.
5 |
6 | Usage
7 | -------------------------------
8 |
9 | ```html
10 |
11 |
12 |
15 |
16 |
17 |
18 |
19 |
20 |
Are you sure you want to change your homepage to Poodle.com ?
21 |
22 |
23 |
35 |
36 | ```
37 |
38 | and js:
39 |
40 | ```javascript
41 | function RootCtrl ($scope) {
42 | $scope.show_modal = true;
43 |
44 | $scope.close_modal = function(){
45 | $scope.show_modal = false;
46 | }
47 | }
48 | ```
49 |
50 | Contribution
51 | -------------------------------
52 |
53 | 1. Fork main [repository](https://github.com/angularify/angular-semantic-ui).
54 | 2. Make changes.
55 | 3. Create issue.
56 | 4. Send pull request.
57 | 5. Thank you.
58 |
59 | TODO
60 | -------------------------------
61 |
62 | 1. Add different modal types.
--------------------------------------------------------------------------------
/src/modal/docs/controllers.js:
--------------------------------------------------------------------------------
1 | angular
2 | .module('modalApp', ['angularify.semantic.modal'])
3 | .controller('RootCtrl', RootCtrl);
4 |
5 | function RootCtrl($scope) {
6 | $scope.show_modal = false;
7 |
8 | $scope.open_modal = function () {
9 | $scope.show_modal = true;
10 | };
11 |
12 | $scope.close_modal = function (){
13 | $scope.show_modal = false;
14 | };
15 | }
--------------------------------------------------------------------------------
/src/modal/docs/demo.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Semantic UI + Angular.JS
6 |
7 |
8 |
9 | Open
10 |
11 |
12 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
We've grabbed the following image from the gravatar image associated with your registered e-mail address.
22 |
Is it okay to use this photo?
23 |
24 |
25 |
26 |
27 | Nope
28 |
29 |
30 | Yep, that's me
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/src/modal/modal.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | angular.module('angularify.semantic.modal', [])
4 |
5 | .directive('modal', function () {
6 | return {
7 | restrict: 'E',
8 | replace: true,
9 | transclude: true,
10 | require: 'ngModel',
11 | template: '
',
12 | link: function (scope, element, attrs, ngModel) {
13 | element.modal({
14 | onHide: function () {
15 | ngModel.$setViewValue(false);
16 | }
17 | });
18 | scope.$watch(function () {
19 | return ngModel.$modelValue;
20 | }, function (modelValue){
21 | element.modal(modelValue ? 'show' : 'hide');
22 | });
23 | scope.$on('$destroy', function() {
24 | element.modal('hide');
25 | element.remove();
26 | });
27 | }
28 | }
29 | });
30 |
--------------------------------------------------------------------------------
/src/modal/test/modal.spec.js:
--------------------------------------------------------------------------------
1 | describe('modal', function () {
2 | var $scope;
3 |
4 | beforeEach(module('angularify.semantic.modal'));
5 |
6 | beforeEach(inject(function ($rootScope) {
7 | $scope = $rootScope;
8 | }));
9 | });
--------------------------------------------------------------------------------
/src/popup/README.md:
--------------------------------------------------------------------------------
1 | angularify.semantic.popup
2 | ===============================
3 |
4 | `angularify.semantic.popup` - popup directive for angular.js.
5 |
6 | Usage
7 | -------------------------------
8 |
9 | ```html
10 |
15 | ```
16 |
17 | `position` - can be: `bottom`, `top`, `right` or `left`.
18 |
19 | `size` - can be: `small` or `large`.
20 |
21 | Contribution
22 | -------------------------------
23 |
24 | 1. Fork main [repository](https://github.com/angularify/angular-semantic-ui).
25 | 2. Make changes.
26 | 3. Create issue.
27 | 4. Send pull request.
28 | 5. Thank you.
29 |
30 | TODO
31 | -------------------------------
32 |
33 | 1. Add animation.
--------------------------------------------------------------------------------
/src/popup/docs/controllers.js:
--------------------------------------------------------------------------------
1 | var popupApp = angular.module('popupApp', ['angularify.semantic.popup']);
2 |
3 | function RootCtrl ($scope) {
4 |
5 | }
--------------------------------------------------------------------------------
/src/popup/docs/demo.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Semantic UI + Angular.JS
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/src/popup/popup.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | angular.module('angularify.semantic.popup', [])
4 |
5 | .directive('popup', function ($document) {
6 | return {
7 | restrict: "A",
8 | scope : {
9 | popup : "@"
10 | },
11 | link: function(scope, element, attrs) {
12 | var class_name = '';
13 | // convert to json
14 | var popup_meta_data = eval('(' + scope.popup + ')');
15 |
16 | var title = popup_meta_data['title'];
17 | if (title == undefined)
18 | title = '';
19 |
20 | var content = popup_meta_data['content'];
21 | if (content == undefined)
22 | content = '';
23 |
24 | var position = popup_meta_data['position'];
25 | if (position == undefined)
26 | position = 'top';
27 |
28 | var size = popup_meta_data['size'];
29 | if (size == undefined)
30 | size = 'small';
31 |
32 | if (position == 'left') {
33 | class_name = 'ui popup left center transition visible ' + size;
34 | } else if (position == 'right') {
35 | class_name = 'ui popup right center transition visible ' + size;
36 | } else if (position == 'bottom') {
37 | class_name = 'ui popup bottom center transition visible ' + size;
38 | } else {
39 | class_name = 'ui popup top center transition visible ' + size;
40 | }
41 |
42 | //
43 | // Get element X/Y of left corner
44 | //
45 | function getPos(ele){
46 | var x = 0;
47 | var y = 0;
48 | while(true){
49 | x += ele.offsetLeft;
50 | y += ele.offsetTop;
51 | if(ele.offsetParent === null)
52 | break;
53 | ele = ele.offsetParent;
54 | }
55 | return [x, y];
56 | }
57 |
58 | var current_element_position_top_left = getPos(element[0]);
59 | var current_element_height = element[0].offsetHeight;
60 | var current_element_width = element[0].offsetWidth;
61 |
62 | //
63 | // Remove element by class name
64 | //
65 | NodeList.prototype.remove = HTMLCollection.prototype.remove = function() {
66 | for(var i = 0, len = this.length; i < len; i++) {
67 | if(this[i] && this[i].parentElement) {
68 | this[i].parentElement.removeChild(this[i]);
69 | }
70 | }
71 | }
72 |
73 | //
74 | // Handle mouse over
75 | //
76 | element.bind('mouseenter', function(){
77 | var html = '';
78 |
79 | angular.element(element[0]).append(html);
80 |
81 | var popupHeight = document.getElementById('my-popup').clientHeight;
82 | var popupWidth = document.getElementById('my-popup').clientWidth;
83 |
84 | if (position == 'left') {
85 | document.getElementById('my-popup').style.top = current_element_position_top_left[1] + (current_element_height / 2) - (popupHeight / 2) + 'px';
86 | document.getElementById('my-popup').style.right = 'auto';
87 | document.getElementById('my-popup').style.left = current_element_position_top_left[0] - popupWidth - 10 + 'px';
88 | document.getElementById('my-popup').style.bottom = 'auto';
89 | document.getElementById('my-popup').style.display = 'inline-block';
90 | } else if (position == 'right') {
91 | document.getElementById('my-popup').style.top = current_element_position_top_left[1] + (current_element_height / 2) - (popupHeight / 2) + 'px';
92 | document.getElementById('my-popup').style.right = 'auto';
93 | document.getElementById('my-popup').style.left = current_element_position_top_left[0] + current_element_width + 'px';
94 | document.getElementById('my-popup').style.bottom = 'auto';
95 | document.getElementById('my-popup').style.display = 'inline-block';
96 | } else if (position == 'bottom') {
97 | document.getElementById('my-popup').style.top = current_element_position_top_left[1] + current_element_height + 'px';
98 | document.getElementById('my-popup').style.left = current_element_position_top_left[0] + (current_element_width / 2) - (popupWidth / 2) + 15 + 'px';
99 | document.getElementById('my-popup').style.right = 'auto';
100 | document.getElementById('my-popup').style.bottom = 'auto';
101 | document.getElementById('my-popup').style.display = 'inline-block';
102 | } else {
103 | document.getElementById('my-popup').style.top = current_element_position_top_left[1] - popupHeight - 10 + 'px';
104 | document.getElementById('my-popup').style.left = current_element_position_top_left[0] + (current_element_width / 2) - (popupWidth / 2) + 18 + 'px';
105 | document.getElementById('my-popup').style.right = 'auto';
106 | document.getElementById('my-popup').style.bottom = 'auto';
107 | document.getElementById('my-popup').style.display = 'inline-block';
108 | }
109 | });
110 |
111 | //
112 | // Handle mouse leave
113 | //
114 | element.bind('mouseleave', function(){
115 | document.getElementsByClassName("ui popup bottom center transition visible").remove();
116 | if (document.getElementById('my-popup') !== null)
117 | document.getElementById('my-popup').remove();
118 | });
119 | }
120 | }
121 | });
--------------------------------------------------------------------------------
/src/popup/test/popup.spec.js:
--------------------------------------------------------------------------------
1 | describe('popup', function () {
2 | var $scope;
3 |
4 | beforeEach(module('angularify.semantic.popup'));
5 |
6 | beforeEach(inject(function ($rootScope) {
7 | $scope = $rootScope;
8 | }));
9 | });
--------------------------------------------------------------------------------
/src/rating/README.md:
--------------------------------------------------------------------------------
1 | angularify.semantic.rating
2 | ===============================
3 |
4 | `angularify.semantic.rating` - rating directive for angular.js.
5 |
6 | Usage
7 | -------------------------------
8 |
9 | ```html
10 |
11 | ```
12 |
13 | ```javascript
14 | var ratingApp = angular.module('ratingApp', ['angularify.semantic.rating']);
15 |
16 | function RootCtrl ($scope) {
17 | $scope.rating = 2;
18 | }
19 | ```
20 |
21 | **IMPORTANT** Every `` must have unique `id` attribute.
22 |
23 | Rating can have following properties:
24 |
25 | * `size` - can be: `small`, `large`, `huge` or `undefined`
26 |
27 | * `type` - can be any icon class (see [semantic-ui](http://semantic-ui.com/elements/icon.html) docs)
28 |
29 | * `ng-model` - return `Int` number: 0..5 (current rating)
30 |
31 |
32 | Contribution
33 | -------------------------------
34 |
35 | 1. Fork main [repository](https://github.com/angularify/angular-semantic-ui).
36 | 2. Make changes.
37 | 3. Create issue.
38 | 4. Send pull request.
39 | 5. Thank you.
40 |
41 | TODO
42 | ------------------------------
43 |
44 | 1. Add more tests.
--------------------------------------------------------------------------------
/src/rating/docs/controllers.js:
--------------------------------------------------------------------------------
1 | var ratingApp = angular.module('ratingApp', ['angularify.semantic.rating']);
2 |
3 | function RootCtrl ($scope) {
4 | // $scope.rating = 1;
5 | }
6 |
--------------------------------------------------------------------------------
/src/rating/docs/demo.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Semantic UI + Angular.JS
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/src/rating/rating.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | angular.module('angularify.semantic.rating', [])
4 |
5 | .directive('rating', function(){
6 | return {
7 | restrict: "E",
8 | replace: true,
9 | transclude: true,
10 | scope: {
11 | id: "@",
12 | size: "@",
13 | type: "@",
14 | model : '=ngModel'
15 | },
16 | template: '' +
17 | ' ' +
18 | ' ' +
19 | ' ' +
20 | ' ' +
21 | ' ' +
22 | '
',
23 | link: function(scope, element, attrs){
24 | if (scope.model == undefined)
25 | scope.model = 0;
26 |
27 | if (scope.model < 1 && scope.model > 5)
28 | scope.model = 0;
29 |
30 | // is rating already checked
31 | var checked = false;
32 |
33 | //
34 | // Set up icon type
35 | //
36 | if (scope.type == undefined)
37 | scope.type = 'star';
38 |
39 | //
40 | // Set up size
41 | //
42 | if (scope.size == undefined)
43 | scope.div_class = 'ui rating ' + scope.type;
44 | else if (scope.size == 'small')
45 | scope.div_class = 'ui small ' + scope.type + ' rating';
46 | else if (scope.size == 'large')
47 | scope.div_class = 'ui large ' + scope.type + ' rating';
48 | else if (scope.size == 'huge')
49 | scope.div_class = 'ui huge ' + scope.type + ' rating';
50 |
51 | //
52 | // set up icon class
53 | //
54 | scope.icon_class = 'icon';
55 |
56 | //
57 | // Handle mouse enter
58 | //
59 | scope.mouse_enter = function(icon_index){
60 | if (checked == true)
61 | return;
62 |
63 | var i = 1;
64 | for (i; i <= icon_index; i++){
65 | document.getElementById(scope.id + i).className = 'icon active';
66 | }
67 |
68 | return;
69 | };
70 |
71 | //
72 | // Handle mouse leave
73 | //
74 | scope.mouse_leave = function(icon_index){
75 | if (checked == true)
76 | return;
77 |
78 | var i = 1;
79 | for (i; i <= 5; i++){
80 | document.getElementById(scope.id + i).className = 'icon';
81 | }
82 |
83 | return;
84 | };
85 |
86 | //
87 | // Handle click
88 | //
89 | scope.click = function(icon_index, mode){
90 | var i = 1;
91 | for (i; i <= icon_index; i++){
92 | document.getElementById(scope.id + i).className = 'icon active';
93 | }
94 |
95 | if (icon_index !== 0)
96 | checked = true;
97 |
98 | return;
99 | };
100 |
101 | //
102 | // Watch for model
103 | //
104 | scope.$watch('model', function(val){
105 | scope.click(val);
106 | });
107 | }
108 | };
109 | });
110 |
--------------------------------------------------------------------------------
/src/rating/test/rating.spec.js:
--------------------------------------------------------------------------------
1 | describe('rating', function () {
2 | var $scope;
3 |
4 | beforeEach(module('angularify.semantic.rating'));
5 |
6 | beforeEach(inject(function ($rootScope) {
7 | $scope = $rootScope;
8 | }));
9 | });
10 |
--------------------------------------------------------------------------------
/src/sidebar/README.md:
--------------------------------------------------------------------------------
1 | angularify.semantic.sidebar
2 | ===============================
3 |
4 | `angularify.semantic.sidebar` - sidebar directive for angular.js.
5 |
6 | Usage
7 | -------------------------------
8 |
9 | ```html
10 |
11 |
12 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 | ```
32 |
33 | ```javascript
34 | angular
35 | .module('sidebarApp', ['angularify.semantic.sidebar'])
36 | .controller('RootCtrl', RootCtrl);
37 |
38 | function RootCtrl ($scope) {
39 | $scope.isOpen = false;
40 | }
41 | ```
42 | `` - can have following properties:
43 |
44 | * `button-class` - attach a selector that open the sidebar
45 |
46 | `` - can have following properties:
47 |
48 | * `title` - group title
49 |
50 | `` - can have following properties:
51 |
52 | * `title` - link text
53 | * `icon` - icon name
54 | * `href` - link address
55 |
56 |
57 | Contribution
58 | -------------------------------
59 |
60 | 1. Fork main [repository](https://github.com/angularify/angular-semantic-ui).
61 | 2. Make changes.
62 | 3. Create issue.
63 | 4. Send pull request.
64 | 5. Thank you.
65 |
66 | TODO
67 | ------------------------------
68 |
69 | 1. Add more tests.
70 | 2. Add different sidebar types.
71 |
--------------------------------------------------------------------------------
/src/sidebar/docs/controllers.js:
--------------------------------------------------------------------------------
1 | angular
2 | .module('sidebarApp', ['angularify.semantic.sidebar'])
3 | .controller('RootCtrl', RootCtrl);
4 |
5 | function RootCtrl ($scope) {
6 | $scope.isOpen = false;
7 | }
--------------------------------------------------------------------------------
/src/sidebar/docs/demo.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Semantic UI + Angular.JS
6 |
7 |
8 |
9 |
10 |
11 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/src/sidebar/sidebar.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | angular
4 | .module('angularify.semantic.sidebar', [])
5 | .directive('sidebar', sidebar)
6 | .directive('sidebarLink', sidebarLink)
7 | .directive('sidebarItem', sidebarItem)
8 | .directive('sidebarItemGroup', sidebarItemGroup);
9 |
10 | function sidebar() {
11 | return {
12 | restrict: 'E',
13 | replace: true,
14 | transclude: true,
15 | template: '',
17 | scope: {
18 | buttonClass: '@'
19 | },
20 | link: function (scope, element, attrs) {
21 | element.sidebar('attach events', scope.buttonClass, 'show');
22 | }
23 | };
24 | }
25 |
26 | function sidebarItemGroup() {
27 | return {
28 | restrict: 'E',
29 | replace: true,
30 | transclude: true,
31 | template: '' +
32 | '' +
33 | '' +
34 | '
',
35 | scope: {
36 | title: '@'
37 | }
38 | };
39 | }
40 |
41 | function sidebarItem() {
42 | return {
43 | restrict: 'E',
44 | replace: true,
45 | transclude: true,
46 | template: '
'
47 | };
48 | }
49 |
50 | function sidebarLink() {
51 | return {
52 | restrict: 'E',
53 | replace: true,
54 | template: '' +
55 | ' ' +
56 | '{{ title }}' +
57 | ' ',
58 | scope: {
59 | title: '@',
60 | icon: '@',
61 | href: '@'
62 | }
63 | };
64 | }
--------------------------------------------------------------------------------
/src/sidebar/test/sidebar.spec.js:
--------------------------------------------------------------------------------
1 | describe('sidebar', function () {
2 | var $scope;
3 |
4 | beforeEach(module('angularify.semantic.sidebar'));
5 |
6 | beforeEach(inject(function ($rootScope) {
7 | $scope = $rootScope;
8 | }));
9 | });
--------------------------------------------------------------------------------
/src/wizard/README.md:
--------------------------------------------------------------------------------
1 | angularify.semantic.wizard
2 | ===============================
3 |
4 | `angularify.semantic.wizard` - wizard/steps directive for angular.js.
5 |
6 | CREDIT
7 | --------------------
8 |
9 | This Wizard is a port of the angular-wizard by mgonto from [github](https://github.com/mgonto/angular-wizard)
10 |
11 | Usage
12 | --------------------
13 | ```html
14 |
15 |
16 | Step 1
17 |
23 |
24 |
25 | Step 2
26 |
33 |
34 |
35 | ```
36 |
37 |
38 | `wizard` - can have following attributes:
39 |
40 | * `fullwidth` - Go fullwidth for the steps bar;
41 | * `current-step` - Updated each time a new step is selected
42 | * `on-finish` - Function to call when a button with `wd-finish` will be clicked
43 |
44 |
45 | `wizard-pane` - can have the following attributes
46 |
47 | * `title` - Title of the Step in the wizard
48 |
49 | `Buttons` - There are 4 types of buttons that go in forms to move a wizards direction
50 |
51 | * `wz-next` - next page
52 | * `wz-previous` - previous page
53 | * `wz-finish` - finish Wizard
54 | * `wz-cancel` - cancel wizard
--------------------------------------------------------------------------------
/src/wizard/doc/controllers.js:
--------------------------------------------------------------------------------
1 |
2 | angular
3 | .module('dropdownApp', ['angularify.semantic.wizard'])
4 | .controller('RootCtrl', RootCtrl);
5 |
6 | function RootCtrl ($scope) {
7 | $scope.currentStep = '';
8 |
9 | $scope.callme = function () {
10 | console.log('finished');
11 | }
12 | }
13 |
14 |
--------------------------------------------------------------------------------
/src/wizard/doc/demo.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Semantic UI + Angular.JS
6 |
7 |
8 |
9 | Wizard
10 |
11 |
12 | Current step: {{ currentStep }}
13 |
14 |
15 |
16 | Finished!
17 |
18 |
19 |
20 |
21 | Step 1
22 |
28 |
29 |
30 | Step 2
31 |
37 |
38 |
39 | Step 3
40 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/src/wizard/test/wizard.spec.js:
--------------------------------------------------------------------------------
1 | describe('wizard', function () {
2 |
3 | beforeEach(module('angularify.semantic.wizard'));
4 |
5 | describe('controller', function () {
6 | var controller,
7 | scope;
8 |
9 | beforeEach(inject(function ($controller, $rootScope) {
10 | scope = $rootScope.$new();
11 | controller = $controller('WizardController', { $scope: scope });
12 | }));
13 |
14 | describe('with 2 steps', function() {
15 | it("should contain 2 steps", function () {
16 | controller.addStep({ title: 'step1' });
17 | controller.addStep({ title: 'step2' });
18 | expect(scope.steps.length).toBe(2);
19 | });
20 | });
21 | });
22 |
23 | describe('directive (wizard)', function () {
24 | var controller,
25 | scope,
26 | elm;
27 |
28 | beforeEach(inject(function ($rootScope, $compile) {
29 | scope = $rootScope;
30 | elm = angular.element('' +
31 | 'Step 1 ' +
32 | 'Step 2 ' +
33 | 'Step 3 ' +
34 | ' ');
35 | $compile(elm)(scope);
36 | scope.$digest();
37 | }));
38 |
39 | it('should create a .steps div', function () {
40 | expect(elm.find('.steps').length).toBe(1);
41 | });
42 |
43 | it('should create a have class `three`', function () {
44 | expect(elm.find('.steps').hasClass('three')).toBeTruthy();
45 | });
46 |
47 | it('should contain 3 wizard pane', function () {
48 | expect(elm.find('.ui.segment').length).toBe(3);
49 | });
50 | });
51 |
52 | describe('directive (wizard-pane)', function () {
53 | var controller,
54 | scope,
55 | elm,
56 | subElm;
57 |
58 | beforeEach(inject(function ($rootScope, $compile) {
59 | scope = $rootScope;
60 | elm = angular.element(' ');
61 | subElm = angular.element('Step 1 ');
62 |
63 | elm.append(subElm);
64 |
65 | $compile(elm)(scope);
66 | scope.$digest();
67 | }));
68 |
69 |
70 | it('should contain a h1', function () {
71 | expect(elm.find('h1').length).toBe(1);
72 | });
73 | });
74 | });
--------------------------------------------------------------------------------
/src/wizard/wizard.js:
--------------------------------------------------------------------------------
1 | /* globals _:false */
2 | 'use strict';
3 | angular.module('angularify.semantic.wizard', [])
4 |
5 | .controller('WizardController', ['$scope',
6 | function($scope) {
7 | $scope.steps = [];
8 | $scope.currentStep = null;
9 | $scope.stepsLength = '';
10 |
11 | $scope.$watch('currentStep', function (step) {
12 | if (!step) return;
13 | var stepTitle = $scope.selectedStep.title;
14 | if ($scope.selectedStep && stepTitle !== $scope.currentStep) {
15 | $scope.goTo($scope.steps.filter(function (step) {
16 | return step.title ==- $scope.currentStep;
17 | })[0]);
18 | }
19 | });
20 |
21 | $scope.$watch('[editMode, steps.length]', function () {
22 | var editMode = $scope.editMode;
23 | if (editMode === undefined || editMode === null) return;
24 |
25 | if (editMode) {
26 | $scope.steps.forEach(function (step) {
27 | step.completed = true;
28 | });
29 | }
30 | }, true);
31 |
32 | this.addStep = function (step) {
33 | $scope.steps.push(step);
34 | if ($scope.steps.length === 1) {
35 | $scope.goTo($scope.steps[0]);
36 | }
37 | };
38 |
39 | $scope.goTo = function (step) {
40 | unselectAll();
41 | $scope.selectedStep = step;
42 |
43 | if ($scope.currentStep !== undefined) {
44 | $scope.currentStep = step.title;
45 | }
46 |
47 | step.selected = true;
48 | $scope.$emit('wizard:stepChanged', {
49 | step: step,
50 | index: $scope.steps.indexOf(step)
51 | });
52 | };
53 |
54 | function unselectAll() {
55 | $scope.steps.forEach(function (step) {
56 | step.selected = false;
57 | });
58 | $scope.selectedStep = null;
59 | }
60 |
61 | this.next = function () {
62 | var index = $scope.steps.indexOf($scope.selectedStep);
63 | $scope.selectedStep.completed = true;
64 | if (index === $scope.steps.length - 1) {
65 | this.finish();
66 | } else {
67 | $scope.goTo($scope.steps[index + 1]);
68 | }
69 | };
70 |
71 | this.goTo = function (step) {
72 | var stepTo;
73 |
74 | if (angular.isNumber(step)) {
75 | stepTo = $scope.steps[step];
76 | } else {
77 | stepTo = $scope.steps.filter(function (step) {
78 | return step.title === step;
79 | })[0];
80 | }
81 | $scope.goTo(stepTo);
82 | };
83 |
84 | this.finish = function() {
85 | if ($scope.onFinish) {
86 | $scope.selectedStep.completed = true;
87 | $scope.onFinish();
88 | }
89 | };
90 |
91 | this.cancel = this.previous = function() {
92 | var index = $scope.steps.indexOf($scope.selectedStep);
93 | if (index === 0) {
94 | throw new Error('Cant go back. Its already in step 0');
95 | } else {
96 | $scope.goTo($scope.steps[index - 1]);
97 | }
98 | };
99 |
100 | $scope.getStatus = function (step) {
101 | var statusClass = [];
102 |
103 | if (step.selected)
104 | statusClass.push('active');
105 | if (!step.selected && !step.completed)
106 | statusClass.push('disabled');
107 | if (step.completed)
108 | statusClass.push('completed');
109 |
110 | return statusClass;
111 | };
112 | }
113 | ])
114 | .directive('wizard', function() {
115 | return {
116 | restrict: 'EA',
117 | replace: true,
118 | transclude: true,
119 | scope: {
120 | fullwidth: "@",
121 | currentStep: '=?',
122 | onFinish: '&',
123 | editMode: '=',
124 | name: '@'
125 | },
126 | controller: 'WizardController',
127 | template: '' +
128 | '
' +
129 | '
' +
130 | '{{step.title}}' +
131 | '
' +
132 | '
' +
133 | '
' +
134 | '
' +
135 | '
',
136 | link: function(scope, element, attrs, WizardController) {
137 | if (scope.fullwidth === 'true') {
138 | var widthmatrix = {
139 | 0: '',
140 | 1: 'one',
141 | 2: 'two',
142 | 3: 'three',
143 | 4: 'four',
144 | 5: 'five',
145 | 6: 'six',
146 | 7: 'seven',
147 | 8: 'eight',
148 | 9: 'nine',
149 | 10: 'ten'
150 | };
151 | scope.stepsLength = widthmatrix[scope.steps.length];
152 | }
153 |
154 | }
155 | };
156 | })
157 | .directive('wizardPane', function() {
158 | return {
159 | restrict: 'EA',
160 | replace: true,
161 | transclude: true,
162 | require: '^wizard',
163 | controller: 'WizardController',
164 | scope: {
165 | title: '@'
166 | },
167 | template: '
',
168 | link: function(scope, element, attrs, WizardController) {
169 | WizardController.addStep(scope);
170 | }
171 | };
172 | });
173 |
174 | function wizardButtonDirective(action) {
175 | angular.module('angularify.semantic.wizard')
176 | .directive(action, function () {
177 | return {
178 | restrict: 'A',
179 | replace: false,
180 | require: '^wizard',
181 | link: function ($scope, $element, $attrs, wizard) {
182 | $scope.noMargin = { margin: 0 };
183 | $element.on('click', function (e) {
184 | e.preventDefault();
185 | $scope.$apply(function () {
186 | $scope.$eval($attrs[action]);
187 | wizard[action.replace('wz', '').toLowerCase()]();
188 | });
189 | });
190 | }
191 | };
192 | });
193 | }
194 |
195 | wizardButtonDirective('wzNext');
196 | wizardButtonDirective('wzPrevious');
197 | wizardButtonDirective('wzFinish');
198 | wizardButtonDirective('wzCancel');
199 |
--------------------------------------------------------------------------------