diff --git a/index.html b/index.html
new file mode 100644
index 0000000..dfcc3bd
--- /dev/null
+++ b/index.html
@@ -0,0 +1,85 @@
+
+
+
+
+
+ Document
+
+
+
+
+
+
+
+
+
+
+
+
+ Level 1
+
+
+ Welcome to level 1
+
+
+
+ Level 1A
+
+
+
+ Level 1A Contents
+
+
+
+
+ Level 1A-A
+
+
+ Level 1A-A Contents
+
+
+
+ Level 1A-B
+
+
+ Level 1A-B Contents
+
+
+
+
+
+
+ Level 1B
+
+
+ Level 1B Contents
+
+
+
+ Level 1C
+
+
+ Level 1C Contents
+
+
+
+
+
+
+ Level 2
+
+
+ Welcome to level 2
+
+
+
+ Level 3
+
+
+ Welcome to level 3
+
+
+
+
+
+
\ No newline at end of file
diff --git a/karma.conf.js b/karma.conf.js
index bac5982..c81af87 100644
--- a/karma.conf.js
+++ b/karma.conf.js
@@ -1,91 +1,90 @@
module.exports = function(config) {
- config.set({
+ config.set({
- // base path that will be used to resolve all patterns (eg. files, exclude)
- basePath: '',
+ // base path that will be used to resolve all patterns (eg. files, exclude)
+ basePath: '',
- // frameworks to use
- // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
- frameworks: ['jasmine'],
+ // frameworks to use
+ // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
+ frameworks: ['jasmine'],
- // list of files / patterns to load in the browser
- files: [
- './node_modules/jquery/dist/jquery.js',
- './node_modules/phantomjs-polyfill/bind-polyfill.js',
- './node_modules/angular/angular.js',
- './node_modules/angular-mocks/angular-mocks.js',
- { pattern: 'spec.bundle.js', watched: false }
- ],
+ // list of files / patterns to load in the browser
+ files: [
+ './node_modules/jquery/dist/jquery.js',
+ './node_modules/phantomjs-polyfill/bind-polyfill.js',
+ './node_modules/angular/angular.js',
+ './node_modules/angular-mocks/angular-mocks.js',
+ { pattern: 'spec.bundle.js', watched: false }
+ ],
- // list of files to exclude
- exclude: [
- ],
+ // list of files to exclude
+ exclude: [],
- plugins: [
- require("karma-phantomjs-launcher"),
- require("karma-sourcemap-loader"),
- require('karma-jasmine'),
- require('karma-webpack')
- ],
+ plugins: [
+ require("karma-phantomjs-launcher"),
+ require("karma-sourcemap-loader"),
+ require('karma-jasmine'),
+ require('karma-webpack')
+ ],
- // preprocess matching files before serving them to the browser
- // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
- preprocessors: {
- 'spec.bundle.js': ['webpack', 'sourcemap']
- },
+ // preprocess matching files before serving them to the browser
+ // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
+ preprocessors: {
+ 'spec.bundle.js': ['webpack', 'sourcemap']
+ },
- webpack: {
- devtools: 'inline-source-map',
- module: {
- preLoaders: [
- { test: /\.ts$/, exclude: /node_modules/, loader: 'tslint-loader' }
- ],
- loaders: [
- { test: /\.ts?$/, exclude: /node_modules/, loader: 'ts-loader' },
- { test: /\.json?$/, exclude: /node_modules/, loader: 'json-loader' }
- ]
- },
- tslint: {
- configuration: require('./tslint.json')
- },
- resolve: {
- extensions: ['', '.ts', '.js']
- }
- },
+ webpack: {
+ devtools: 'inline-source-map',
+ module: {
+ preLoaders: [
+ { test: /\.ts$/, exclude: /node_modules/, loader: 'tslint-loader' }
+ ],
+ loaders: [
+ { test: /\.ts?$/, exclude: /node_modules/, loader: 'ts-loader' },
+ { test: /\.json?$/, exclude: /node_modules/, loader: 'json-loader' }
+ ]
+ },
+ tslint: {
+ configuration: require('./tslint.json')
+ },
+ resolve: {
+ extensions: ['', '.ts', '.js']
+ }
+ },
- // test results reporter to use
- // possible values: 'dots', 'progress'
- // available reporters: https://npmjs.org/browse/keyword/karma-reporter
- reporters: ['progress'],
+ // test results reporter to use
+ // possible values: 'dots', 'progress'
+ // available reporters: https://npmjs.org/browse/keyword/karma-reporter
+ reporters: ['progress'],
- // web server port
- port: 9876,
+ // web server port
+ port: 9876,
- // enable / disable colors in the output (reporters and logs)
- colors: true,
+ // enable / disable colors in the output (reporters and logs)
+ colors: true,
- // level of logging
- // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
- logLevel: config.LOG_INFO,
+ // level of logging
+ // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
+ logLevel: config.LOG_INFO,
- // enable / disable watching file and executing tests whenever any file changes
- autoWatch: false,
+ // enable / disable watching file and executing tests whenever any file changes
+ autoWatch: false,
- // start these browsers
- // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
- browsers: ['PhantomJS'],
+ // start these browsers
+ // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
+ browsers: ['PhantomJS'],
- // Continuous Integration mode
- // if true, Karma captures browsers, runs the tests and exits
- singleRun: true
- });
-};
+ // Continuous Integration mode
+ // if true, Karma captures browsers, runs the tests and exits
+ singleRun: true
+ });
+};
\ No newline at end of file
diff --git a/package.json b/package.json
index ae42d2d..d0d135f 100644
--- a/package.json
+++ b/package.json
@@ -1,57 +1,60 @@
{
- "name": "semantic-ui-angular",
- "version": "0.0.0",
- "description": "Pure AngularJS directives to support Semantic-UI components",
- "main": "index.js",
- "scripts": {
- "postinstall": "node_modules/.bin/tsd install",
- "test": "node_modules/karma/bin/karma start",
- "test-dev": "./node_modules/karma/bin/karma start --auto-watch --no-single-run",
- "build": "rm -rf dist && node_modules/.bin/webpack"
- },
- "repository": {
- "type": "git",
- "url": "git+https://github.com/Semantic-Org/Semantic-UI-Angular"
- },
- "keywords": [
- "angularjs",
- "semantic-ui",
- "directives",
- "components",
- "typescript"
- ],
- "author": "",
- "license": "MIT",
- "bugs": {
- "url": "https://github.com/Semantic-Org/Semantic-UI-Angular/issues"
- },
- "homepage": "https://github.com/Semantic-Org/Semantic-UI-Angular#readme",
- "devDependencies": {
- "angular": "1.4.8",
- "angular-mocks": "1.4.8",
- "cz-conventional-changelog": "^1.1.5",
- "jasmine-core": "2.4.1",
- "jquery": "2.2.0",
- "jscs": "2.8.0",
- "jscs-loader": "0.2.0",
- "json-loader": "0.5.4",
- "karma": "0.13.19",
- "karma-jasmine": "0.3.6",
- "karma-phantomjs-launcher": "0.2.3",
- "karma-sourcemap-loader": "0.3.6",
- "karma-webpack": "1.7.0",
- "phantomjs": "1.9.19",
- "phantomjs-polyfill": "0.0.1",
- "ts-loader": "0.7.2",
- "tsd": "0.6.5",
- "tslint": "3.2.1",
- "tslint-loader": "2.1.0",
- "typescript": "1.7.5",
- "webpack": "1.12.10"
- },
- "config": {
- "commitizen": {
- "path": "./node_modules/cz-conventional-changelog"
+ "name": "semantic-ui-angular",
+ "version": "0.0.0",
+ "description": "Pure AngularJS directives to support Semantic-UI components",
+ "main": "index.js",
+ "scripts": {
+ "postinstall": "node_modules/.bin/tsd install",
+ "test": "karma start",
+ "test-dev": "karma start --auto-watch --no-single-run",
+ "build": "rimraf dist && webpack",
+ "start": "webpack-dev-server --inline --progress --port 8080"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/Semantic-Org/Semantic-UI-Angular"
+ },
+ "keywords": [
+ "angularjs",
+ "semantic-ui",
+ "directives",
+ "components",
+ "typescript"
+ ],
+ "author": "",
+ "license": "MIT",
+ "bugs": {
+ "url": "https://github.com/Semantic-Org/Semantic-UI-Angular/issues"
+ },
+ "homepage": "https://github.com/Semantic-Org/Semantic-UI-Angular#readme",
+ "devDependencies": {
+ "angular": "1.6.1",
+ "angular-mocks": "1.6.1",
+ "cz-conventional-changelog": "^1.1.5",
+ "jasmine-core": "2.5.2",
+ "jquery": "3.1.1",
+ "jscs": "3.0.7",
+ "jscs-loader": "0.3.0",
+ "json-loader": "0.5.4",
+ "karma": "1.3.0",
+ "karma-jasmine": "1.1.0",
+ "karma-phantomjs-launcher": "1.0.2",
+ "karma-sourcemap-loader": "0.3.7",
+ "karma-webpack": "1.8.1",
+ "phantomjs": "2.1.7",
+ "phantomjs-polyfill": "0.0.2",
+ "rimraf": "^2.5.4",
+ "ts-loader": "1.3.3",
+ "tsd": "0.6.5",
+ "tslint": "4.2.0",
+ "tslint-loader": "3.3.0",
+ "typescript": "2.1.4",
+ "webpack": "1.14.0",
+ "webpack-dev-server": "^1.16.2"
+ },
+ "config": {
+ "commitizen": {
+ "path": "./node_modules/cz-conventional-changelog"
+ }
}
- }
}
\ No newline at end of file
diff --git a/src/index.ts b/src/index.ts
index 091759c..8939ce1 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,5 +1,7 @@
///
+
+import { smAccordionModule } from './modules/accordion/accordion.module';
import { smButtonModule } from './elements/button/button';
import { smRatingModule } from './modules/rating/rating';
import { smDividerModule } from './elements/divider/divider';
@@ -11,7 +13,9 @@ import { smDividerModule } from './elements/divider/divider';
.module('semantic.ui', [
smButtonModule.name,
smRatingModule.name,
- smDividerModule.name
+ smDividerModule.name,
+
+ smAccordionModule.name
]);
})();
diff --git a/src/modules/accordion/accordion.module.ts b/src/modules/accordion/accordion.module.ts
new file mode 100644
index 0000000..3fc4936
--- /dev/null
+++ b/src/modules/accordion/accordion.module.ts
@@ -0,0 +1,130 @@
+///
+
+'use strict';
+
+interface ISmAccordionSettings {
+ exclusive: Boolean,
+ on: String,
+ animateChildren: Boolean,
+ closeNested: Boolean,
+ collapsible: Boolean,
+ duration: Number,
+ easing: String
+}
+
+const accordionSettings: ISmAccordionSettings = {
+ exclusive: true,
+ on: 'click',
+ animateChildren: true,
+ closeNested: true,
+ collapsible: true,
+ duration: 500,
+ easing: 'easeInOutQuint'
+};
+
+class SmAccordionController {
+ static $inject = ['$scope', '$element', '$attrs'];
+
+ ngModel: ng.INgModelController;
+ accordionGroups = [];
+
+ constructor(public $scope: ng.IScope, public $element: ng.IAugmentedJQuery, public $attrs) {
+
+ }
+
+ addGroup = function (element) {
+ this.accordionGroups.push(element);
+ }
+ setActive = function (title) {
+
+ var content = this.accordionGroups[this.accordionGroups.indexOf(title) + 1];
+
+ if (content && content.hasClass('content')) {
+ content.toggleClass('active');
+ }
+ title.toggleClass('active');
+
+ if (accordionSettings.exclusive) {
+ this.accordionGroups.forEach(e => {
+ if (e != title && e != content)
+ e.removeClass('active')
+ });
+ }
+ }
+}
+
+class SmAccordionDirective implements ng.IDirective {
+ static instance(): ng.IDirective {
+ return new SmAccordionDirective;
+ }
+
+ restrict = 'E';
+ controller = SmAccordionController;
+ controllerAs = 'accordion';
+ replace = true;
+ transclude = true;
+ template = '';
+ link = (
+ scope: ng.IScope,
+ element: ng.IAugmentedJQuery,
+ attrs
+ ) => {
+
+ };
+}
+
+class SmAccordionTitleDirective implements ng.IDirective {
+ static instance(): ng.IDirective {
+ return new SmAccordionTitleDirective;
+ }
+
+ restrict = 'E';
+ replace = true;
+ transclude = true;
+ require = '^smAccordion';
+
+ template = '
';
+
+ link = (
+ scope: ng.IScope,
+ element: ng.IAugmentedJQuery,
+ attrs,
+ ctrl
+ ) => {
+ ctrl.addGroup(element);
+
+ element.bind('click', () => {
+ ctrl.setActive(element);
+ });
+
+ };
+}
+
+class SmAccordionContentDirective implements ng.IDirective {
+ static instance(): ng.IDirective {
+ return new SmAccordionContentDirective;
+ }
+
+ restrict = 'E';
+ replace = true;
+ transclude = true;
+ require = '^smAccordion';
+
+ template = '';
+ link = (
+ scope: ng.IScope,
+ element: ng.IAugmentedJQuery,
+ attrs,
+ ctrl
+ ) => {
+ ctrl.addGroup(element);
+ };
+}
+
+
+export const smAccordionModule = angular
+ .module('semantic.ui.modules.accordion', [])
+ .directive('smAccordion', SmAccordionDirective.instance)
+ .directive('smAccordionTitle', SmAccordionTitleDirective.instance)
+ .directive('smAccordionContent', SmAccordionContentDirective.instance)
+ .constant('smAccordionSettings', accordionSettings);
diff --git a/src/modules/accordion/accordion.spec.ts b/src/modules/accordion/accordion.spec.ts
new file mode 100644
index 0000000..bde5f1f
--- /dev/null
+++ b/src/modules/accordion/accordion.spec.ts
@@ -0,0 +1,180 @@
+///
+///
+
+import { smAccordionModule } from './accordion.module';
+
+describe('Semantic-UI: Components - smAccordion', function () {
+ 'use strict';
+
+ let $scope, $compile, element, settings;
+
+ beforeEach(angular.mock.module(smAccordionModule.name));
+
+ beforeEach(inject(function ($rootScope, $injector, smAccordionSettings) {
+ $scope = $rootScope.$new();
+ $compile = $injector.get('$compile');
+ element = $compile(template)($scope);
+ settings = smAccordionModule;
+ $scope.$digest();
+ }));
+
+ it('expected elements length', function () {
+ expect(element.find('.title').length).toBe(8);
+ expect(element.find('.content').length).toBe(8);
+ });
+
+ it('no one active by default', function () {
+ expect(element.find('.active').length).toBe(0);
+ });
+
+ it('all title have icon', function () {
+ expect(element.find('.title:first').children('i.icon').length).toBe(1);
+ });
+
+
+ it('open first group', function () {
+ var firstTitle = element.find('.title:first');
+ firstTitle.click();
+ $scope.$digest();
+
+ expect(firstTitle.hasClass('active')).toBe(true);
+ expect(firstTitle.next().hasClass('active')).toBe(true);
+
+ var activeTitle = element.find('.title.active');
+ expect(activeTitle.length > 0).toBe(true);
+ activeTitle.click();
+ $scope.$digest();
+ expect(element.find('.title.active').length).toBe(0);
+ expect(element.find('.content.active').length).toBe(0);
+
+ });
+
+ it('exclusive setting', function () {
+ var firstTitle = element.find('.title:first');
+ var lastTitle = element.find('.title:last');
+ firstTitle.click();
+ $scope.$digest();
+
+ expect(firstTitle.hasClass('active')).toBe(true);
+ expect(firstTitle.next().hasClass('active')).toBe(true);
+
+ lastTitle.click();
+ $scope.$digest();
+
+ expect(firstTitle.hasClass('active')).toBe(false);
+ expect(firstTitle.next().hasClass('active')).toBe(false);
+ expect(lastTitle.hasClass('active')).toBe(true);
+ expect(lastTitle.next().hasClass('active')).toBe(true);
+
+ });
+
+});
+
+describe('Semantic-UI: Components - smAccordion - Custom Settings', function () {
+ 'use strict';
+
+ let $scope, $compile, element;
+ let settings = {
+ exclusive: false
+ }
+
+ beforeEach(angular.mock.module(smAccordionModule.name));
+
+ beforeEach(inject(function ($rootScope, $injector, smAccordionSettings) {
+ $scope = $rootScope.$new();
+ $compile = $injector.get('$compile');
+ element = $compile(template)($scope);
+ angular.extend(smAccordionSettings, settings);
+ $scope.$digest();
+ }));
+
+
+
+ it('exclusive setting is false', function () {
+ var firstTitle = element.find('.title:first');
+ var lastTitle = element.find('.title:last');
+ firstTitle.click();
+ $scope.$digest();
+
+ expect(firstTitle.hasClass('active')).toBe(true);
+ expect(firstTitle.next().hasClass('active')).toBe(true);
+
+ lastTitle.click();
+ $scope.$digest();
+
+ expect(firstTitle.hasClass('active')).toBe(true);
+ expect(firstTitle.next().hasClass('active')).toBe(true);
+ expect(lastTitle.hasClass('active')).toBe(true);
+ expect(lastTitle.next().hasClass('active')).toBe(true);
+
+ });
+
+});
+
+
+var template = `
+
+
+ Level 1
+
+
+ Welcome to level 1
+
+
+
+ Level 1A
+
+
+
+ Level 1A Contents
+
+
+
+
+ Level 1A-A
+
+
+ Level 1A-A Contents
+
+
+
+ Level 1A-B
+
+
+ Level 1A-B Contents
+
+
+
+
+
+
+ Level 1B
+
+
+ Level 1B Contents
+
+
+
+ Level 1C
+
+
+ Level 1C Contents
+
+
+
+
+
+
+ Level 2
+
+
+ Welcome to level 2
+
+
+
+ Level 3
+
+
+ Welcome to level 3
+
+ `;
\ No newline at end of file
diff --git a/webpack.config.js b/webpack.config.js
index e493a20..67a6a63 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -3,46 +3,46 @@ var webpack = require('webpack');
var VERSION = require('./package.json').version;
var banner =
- '/*!\n' +
- ' * Semantic-UI AngularJS integration\n' +
- ' * https://github.com/semantic-org/semantic-ui-angular\n' +
- ' * @license MIT\n' +
- ' * v' + VERSION + '\n' +
- ' */\n';
+ '/*!\n' +
+ ' * Semantic-UI AngularJS integration\n' +
+ ' * https://github.com/semantic-org/semantic-ui-angular\n' +
+ ' * @license MIT\n' +
+ ' * v' + VERSION + '\n' +
+ ' */\n';
module.exports = {
- context: path.resolve('src'),
- devtool: "source-map",
- entry: {
- 'semantic-ui-angular': './index',
- 'semantic-ui-angular.min': './index'
- },
- output: {
- path: path.resolve('dist'),
- filename: '[name].js'
- },
- plugins: [
- new webpack.optimize.UglifyJsPlugin({
- include: /\.min\.js$/,
- minimize: true
- }),
- new webpack.BannerPlugin(banner, {raw: true})
- ],
- module: {
- preLoaders: [
- { test: /\.ts$/, exclude: /node_modules/, loader: 'tslint-loader' },
- // TODO(m0t0r): JSCS complains on TS code, decide if we actually can/need make it work
- //{ test: /\.ts$/, exclude: /node_modules/, loader: 'jscs-loader' }
+ context: path.resolve('src'),
+ devtool: "source-map",
+ entry: {
+ 'semantic-ui-angular': './index',
+ 'semantic-ui-angular.min': './index'
+ },
+ output: {
+ path: path.resolve('dist'),
+ filename: '[name].js'
+ },
+ plugins: [
+ // new webpack.optimize.UglifyJsPlugin({
+ // include: /\.min\.js$/,
+ // minimize: true
+ // }),
+ // new webpack.BannerPlugin(banner, {raw: true})
],
- loaders: [
- { test: /\.ts?$/, exclude: /node_modules/, loader: 'ts-loader' },
- { test: /\.json?$/, exclude: /node_modules/, loader: 'json-loader' }
- ]
- },
- tslint: {
- configuration: require('./tslint.json')
- },
- resolve: {
- extensions: ['', '.ts', '.js']
- }
-};
+ module: {
+ preLoaders: [
+ { test: /\.ts$/, exclude: /node_modules/, loader: 'tslint-loader' },
+ // TODO(m0t0r): JSCS complains on TS code, decide if we actually can/need make it work
+ //{ test: /\.ts$/, exclude: /node_modules/, loader: 'jscs-loader' }
+ ],
+ loaders: [
+ { test: /\.ts?$/, exclude: /node_modules/, loader: 'ts-loader' },
+ { test: /\.json?$/, exclude: /node_modules/, loader: 'json-loader' }
+ ]
+ },
+ tslint: {
+ configuration: require('./tslint.json')
+ },
+ resolve: {
+ extensions: ['', '.ts', '.js']
+ }
+};
\ No newline at end of file