├── index.js
├── app
├── pages
│ ├── group
│ │ ├── panels
│ │ │ ├── one
│ │ │ │ ├── onePanel.controller.js
│ │ │ │ └── one.html
│ │ │ └── templated
│ │ │ │ ├── templated.controller.js
│ │ │ │ └── templated.html
│ │ ├── group.html
│ │ └── group.controller.js
│ ├── home
│ │ ├── home.controller.js
│ │ └── home.html
│ ├── autoExpand
│ │ ├── autoExpand.controller.js
│ │ └── autoExpand.html
│ └── multiple
│ │ ├── multiple.controller.js
│ │ └── multiple.html
├── style.css
├── nav.controller.js
├── app.js
└── index.html
├── docs
├── icons
│ └── ic_keyboard_arrow_right_black_24px.svg
├── pages
│ ├── group
│ │ ├── panels
│ │ │ ├── one
│ │ │ │ ├── onePanel.controller.js
│ │ │ │ └── one.html
│ │ │ └── templated
│ │ │ │ ├── templated.controller.js
│ │ │ │ └── templated.html
│ │ ├── group.html
│ │ └── group.controller.js
│ ├── home
│ │ ├── home.controller.js
│ │ └── home.html
│ ├── autoExpand
│ │ ├── autoExpand.controller.js
│ │ └── autoExpand.html
│ └── multiple
│ │ ├── multiple.controller.js
│ │ └── multiple.html
├── style.css
├── expansionPanels.js
├── nav.controller.js
├── js
│ ├── expansionPanelIcon.directive.js
│ ├── expansionPanel.service.js
│ ├── expansionPanelFooter.directive.js
│ ├── expansionPanelHeader.directive.js
│ ├── expansionPanelCollapsed.directive.js
│ ├── expansionPanelExpanded.directive.js
│ ├── expansionPanelGroup.directive.js
│ ├── expansionPanelGroup.service.js
│ └── expansionPanel.directive.js
├── app.js
├── expansionPanels-theme.css
├── index.html
├── expansionPanels.css
└── angular-aria
│ └── angular-aria.js
├── src
├── icons
│ └── ic_keyboard_arrow_right_black_24px.svg
├── expansionPanels.js
├── js
│ ├── expansionPanelIcon.directive.js
│ ├── expansionPanel.service.js
│ ├── expansionPanelFooter.directive.js
│ ├── expansionPanelHeader.directive.js
│ ├── expansionPanelCollapsed.directive.js
│ ├── expansionPanelExpanded.directive.js
│ ├── expansionPanelGroup.directive.js
│ ├── expansionPanelGroup.service.js
│ └── expansionPanel.directive.js
├── expansionPanels-theme.scss
└── expansionPanels.scss
├── gulp
├── config.js
├── indexBuild.js
├── cssBuild.js
└── jsBuild.js
├── .gitignore
├── bower.json
├── LICENSE
├── package.json
├── karma.conf.js
├── gulpfile.js
└── dist
├── md-expansion-panel.min.css
├── md-expansion-panel.css
└── md-expansion-panel.min.js
/index.js:
--------------------------------------------------------------------------------
1 | module.exports = require('./dist/md-expansion-panel');
2 |
--------------------------------------------------------------------------------
/app/pages/group/panels/one/onePanel.controller.js:
--------------------------------------------------------------------------------
1 | angular
2 | .module('angularMaterialExpansionPanel')
3 | .controller('OnePanelController', OnePanelController);
4 |
5 |
6 |
7 | function OnePanelController() {
8 |
9 | }
10 |
--------------------------------------------------------------------------------
/docs/icons/ic_keyboard_arrow_right_black_24px.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/docs/pages/group/panels/one/onePanel.controller.js:
--------------------------------------------------------------------------------
1 | (function(){"use strict";angular
2 | .module('angularMaterialExpansionPanel')
3 | .controller('OnePanelController', OnePanelController);
4 |
5 |
6 |
7 | function OnePanelController() {
8 |
9 | }
10 | }());
--------------------------------------------------------------------------------
/src/icons/ic_keyboard_arrow_right_black_24px.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/src/expansionPanels.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @ngdoc module
3 | * @name material.components.expansionPanels
4 | *
5 | * @description
6 | * Expansion panel component
7 | */
8 | angular
9 | .module('material.components.expansionPanels', [
10 | 'material.core'
11 | ]);
12 |
--------------------------------------------------------------------------------
/docs/style.css:
--------------------------------------------------------------------------------
1 | body {
2 | overflow: hidden;
3 | max-width: 100%;
4 | max-height: 100%; }
5 |
6 | .view-container {
7 | padding-left: 12px;
8 | padding-right: 12px; }
9 |
10 | .nav-bar {
11 | box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12);
12 | background: #FFF;
13 | z-index: 9; }
14 |
--------------------------------------------------------------------------------
/docs/expansionPanels.js:
--------------------------------------------------------------------------------
1 | (function(){"use strict";/**
2 | * @ngdoc module
3 | * @name material.components.expansionPanels
4 | *
5 | * @description
6 | * Expansion panel component
7 | */
8 | angular
9 | .module('material.components.expansionPanels', [
10 | 'material.core'
11 | ]);
12 | }());
--------------------------------------------------------------------------------
/app/style.css:
--------------------------------------------------------------------------------
1 | body {
2 | overflow: hidden;
3 | max-width: 100%;
4 | max-height: 100%;
5 | }
6 |
7 | .view-container {
8 | padding-left: 12px;
9 | padding-right: 12px;
10 | }
11 |
12 |
13 | .nav-bar {
14 | box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12);
15 | background: #FFF;
16 | z-index: 9;
17 | }
18 |
--------------------------------------------------------------------------------
/app/pages/group/panels/templated/templated.controller.js:
--------------------------------------------------------------------------------
1 | angular
2 | .module('angularMaterialExpansionPanel')
3 | .controller('TemplatedPanelController', TemplatedPanelController);
4 |
5 |
6 |
7 | function TemplatedPanelController(title, summary, content) {
8 | var vm = this;
9 |
10 | vm.title = title;
11 | vm.summary = summary;
12 | vm.content = content;
13 | }
14 |
--------------------------------------------------------------------------------
/app/nav.controller.js:
--------------------------------------------------------------------------------
1 | angular
2 | .module('angularMaterialExpansionPanel')
3 | .controller('NavController', NavController);
4 |
5 |
6 |
7 | NavController.$inject = ['$scope', '$rootScope'];
8 | function NavController($scope, $rootScope) {
9 | $rootScope.$on('$routeChangeSuccess', function(event, current) {
10 | $scope.currentNavItem = current.$$route.originalPath || '/';
11 | });
12 | }
13 |
--------------------------------------------------------------------------------
/docs/pages/group/panels/templated/templated.controller.js:
--------------------------------------------------------------------------------
1 | (function(){"use strict";angular
2 | .module('angularMaterialExpansionPanel')
3 | .controller('TemplatedPanelController', TemplatedPanelController);
4 |
5 |
6 |
7 | function TemplatedPanelController(title, summary, content) {
8 | var vm = this;
9 |
10 | vm.title = title;
11 | vm.summary = summary;
12 | vm.content = content;
13 | }
14 | }());
--------------------------------------------------------------------------------
/docs/nav.controller.js:
--------------------------------------------------------------------------------
1 | (function(){"use strict";angular
2 | .module('angularMaterialExpansionPanel')
3 | .controller('NavController', NavController);
4 |
5 |
6 |
7 | NavController.$inject = ['$scope', '$rootScope'];
8 | function NavController($scope, $rootScope) {
9 | $rootScope.$on('$routeChangeSuccess', function(event, current) {
10 | $scope.currentNavItem = current.$$route.originalPath || '/';
11 | });
12 | }
13 | }());
--------------------------------------------------------------------------------
/docs/pages/home/home.controller.js:
--------------------------------------------------------------------------------
1 | (function(){"use strict";angular
2 | .module('angularMaterialExpansionPanel')
3 | .controller('HomeController', HomeController);
4 |
5 |
6 | function HomeController($scope, $mdExpansionPanel) {
7 | $mdExpansionPanel().waitFor('expansionPanelOne').then(function (instance) {
8 | instance.expand();
9 | });
10 |
11 |
12 | $scope.collapseOne = function () {
13 | $mdExpansionPanel('expansionPanelOne').collapse();
14 | };
15 | }
16 | }());
--------------------------------------------------------------------------------
/app/pages/home/home.controller.js:
--------------------------------------------------------------------------------
1 | angular
2 | .module('angularMaterialExpansionPanel')
3 | .controller('HomeController', HomeController);
4 |
5 |
6 | function HomeController($scope, $mdExpansionPanel) {
7 | $mdExpansionPanel().waitFor('expansionPanelOne').then(function (instance) {
8 | instance.expand();
9 | });
10 |
11 |
12 | $scope.collapseOne = function () {
13 | $mdExpansionPanel('expansionPanelOne').collapse();
14 | };
15 |
16 | $scope.isDisabled = true;
17 | }
18 |
--------------------------------------------------------------------------------
/gulp/config.js:
--------------------------------------------------------------------------------
1 | exports.paths = {
2 | src: 'src/',
3 | app: 'app/',
4 | dest: 'public/',
5 | build: 'dist/',
6 | scripts: ['src/expansionPanel.js', 'src/*.js', 'src/**/*.js', '!src/*spec.js', '!src/**/*spec.js'],
7 | appScripts: ['app/app.js', 'app/*.js', 'app/**/*.js'],
8 | css: ['src/*.scss', 'src/*.css', '!src/*spec.css'],
9 | appCss: ['app/style.css', 'app/**/*.css'],
10 | injectCss: ['public/*.css', 'public/**/*.css'],
11 | partials: ['app/**/*.html'],
12 | icons: ['src/**/*.svg'],
13 | bower: './bower.json'
14 | };
15 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 |
6 | # Runtime data
7 | pids
8 | *.pid
9 | *.seed
10 |
11 | # Directory for instrumented libs generated by jscoverage/JSCover
12 | lib-cov
13 |
14 | # Coverage directory used by tools like istanbul
15 | coverage
16 |
17 | # nyc test coverage
18 | .nyc_output
19 |
20 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
21 | .grunt
22 |
23 | # node-waf configuration
24 | .lock-wscript
25 |
26 | # Compiled binary addons (http://nodejs.org/api/addons.html)
27 | build/Release
28 |
29 | # Dependency directories
30 | node_modules
31 | jspm_packages
32 | bower_components
33 |
34 | # Optional npm cache directory
35 | .npm
36 |
37 | # Optional REPL history
38 | .node_repl_history
39 |
40 |
41 | # sass cache
42 | .gulp-scss-cache
43 | .sass-cache
44 |
--------------------------------------------------------------------------------
/src/js/expansionPanelIcon.directive.js:
--------------------------------------------------------------------------------
1 | angular
2 | .module('material.components.expansionPanels')
3 | .directive('mdExpansionPanelIcon', mdExpansionPanelIconDirective);
4 |
5 |
6 |
7 | /**
8 | * @ngdoc directive
9 | * @name mdExpansionPanelIcon
10 | * @module material.components.expansionPanels
11 | *
12 | * @restrict E
13 | *
14 | * @description
15 | * `mdExpansionPanelIcon` can be used in both `md-expansion-panel-collapsed` and `md-expansion-panel-header` as the first or last element.
16 | * Adding this will provide a animated arrow for expanded and collapsed states
17 | **/
18 | function mdExpansionPanelIconDirective() {
19 | var directive = {
20 | restrict: 'E',
21 | template: ' ',
22 | replace: true
23 | };
24 | return directive;
25 | }
26 |
--------------------------------------------------------------------------------
/app/pages/group/panels/one/one.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Title
5 | Summary
6 |
7 |
8 |
9 |
10 |
11 | Expanded Title
12 | Expanded Summary
13 |
14 |
15 |
16 | Content
17 | Put content in here
18 |
19 |
20 |
21 |
22 | Collapse
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/docs/pages/group/panels/one/one.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Title
5 | Summary
6 |
7 |
8 |
9 |
10 |
11 | Expanded Title
12 | Expanded Summary
13 |
14 |
15 |
16 | Content
17 | Put content in here
18 |
19 |
20 |
21 |
22 | Collapse
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/docs/js/expansionPanelIcon.directive.js:
--------------------------------------------------------------------------------
1 | (function(){"use strict";angular
2 | .module('material.components.expansionPanels')
3 | .directive('mdExpansionPanelIcon', mdExpansionPanelIconDirective);
4 |
5 |
6 |
7 | /**
8 | * @ngdoc directive
9 | * @name mdExpansionPanelIcon
10 | * @module material.components.expansionPanels
11 | *
12 | * @restrict E
13 | *
14 | * @description
15 | * `mdExpansionPanelIcon` can be used in both `md-expansion-panel-collapsed` and `md-expansion-panel-header` as the first or last element.
16 | * Adding this will provide a animated arrow for expanded and collapsed states
17 | **/
18 | function mdExpansionPanelIconDirective() {
19 | var directive = {
20 | restrict: 'E',
21 | template: ' ',
22 | replace: true
23 | };
24 | return directive;
25 | }
26 | }());
--------------------------------------------------------------------------------
/app/app.js:
--------------------------------------------------------------------------------
1 | angular.module('angularMaterialExpansionPanel', [
2 | 'ngRoute',
3 | 'ngAnimate',
4 | 'ngMaterial',
5 | 'material.components.expansionPanels'
6 | ])
7 | .config(configApp);
8 |
9 |
10 | configApp.$inject = ['$routeProvider'];
11 | function configApp($routeProvider) {
12 | $routeProvider
13 | .when('/', {
14 | templateUrl: 'pages/home/home.html',
15 | controller: 'HomeController',
16 | controllerAs: 'vm'
17 | })
18 | .when('/group', {
19 | templateUrl: 'pages/group/group.html',
20 | controller: 'GroupController',
21 | controllerAs: 'vm'
22 | })
23 | .when('/autoexpand', {
24 | templateUrl: 'pages/autoExpand/autoExpand.html',
25 | controller: 'AutoExpandController',
26 | controllerAs: 'vm'
27 | })
28 | .when('/multiple', {
29 | templateUrl: 'pages/multiple/multiple.html',
30 | controller: 'MultipleController',
31 | controllerAs: 'vm'
32 | })
33 | .otherwise('/');
34 | }
35 |
--------------------------------------------------------------------------------
/app/pages/group/panels/templated/templated.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{vm.title}}
5 | {{vm.summary}}
6 |
7 |
8 |
9 |
10 |
11 | {{vm.title}}
12 | {{vm.summary}}
13 |
14 |
15 |
16 | Content
17 |
18 | {{vm.content}}
19 |
20 |
21 |
22 |
23 |
24 | Remove
25 | Collapse
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/docs/pages/group/panels/templated/templated.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{vm.title}}
5 | {{vm.summary}}
6 |
7 |
8 |
9 |
10 |
11 | {{vm.title}}
12 | {{vm.summary}}
13 |
14 |
15 |
16 | Content
17 |
18 | {{vm.content}}
19 |
20 |
21 |
22 |
23 |
24 | Remove
25 | Collapse
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/docs/app.js:
--------------------------------------------------------------------------------
1 | (function(){"use strict";angular.module('angularMaterialExpansionPanel', [
2 | 'ngRoute',
3 | 'ngAnimate',
4 | 'ngMaterial',
5 | 'material.components.expansionPanels'
6 | ])
7 | .config(configApp);
8 |
9 |
10 | configApp.$inject = ['$routeProvider'];
11 | function configApp($routeProvider) {
12 | $routeProvider
13 | .when('/', {
14 | templateUrl: 'pages/home/home.html',
15 | controller: 'HomeController',
16 | controllerAs: 'vm'
17 | })
18 | .when('/group', {
19 | templateUrl: 'pages/group/group.html',
20 | controller: 'GroupController',
21 | controllerAs: 'vm'
22 | })
23 | .when('/autoexpand', {
24 | templateUrl: 'pages/autoExpand/autoExpand.html',
25 | controller: 'AutoExpandController',
26 | controllerAs: 'vm'
27 | })
28 | .when('/multiple', {
29 | templateUrl: 'pages/multiple/multiple.html',
30 | controller: 'MultipleController',
31 | controllerAs: 'vm'
32 | })
33 | .otherwise('/');
34 | }
35 | }());
--------------------------------------------------------------------------------
/src/expansionPanels-theme.scss:
--------------------------------------------------------------------------------
1 | md-expansion-panel {
2 | background: #FFF;
3 |
4 | md-expansion-panel-collapsed,
5 | .md-expansion-panel-footer-container,
6 | .md-expansion-panel-header-container {
7 | background: #FFF;
8 |
9 | .md-title,
10 | .md-summary {
11 | color: #333;
12 | }
13 | }
14 |
15 |
16 | md-expansion-panel-footer .md-expansion-panel-footer-container,
17 | md-expansion-panel-header .md-expansion-panel-header-container {
18 | border-color: #DDD;
19 | }
20 |
21 | .md-expansion-panel-icon svg {
22 | fill: #999;
23 | }
24 |
25 |
26 | &[disabled] {
27 | md-expansion-panel-collapsed {
28 | .md-title,
29 | .md-summary {
30 | color: #DDD;
31 | }
32 | }
33 |
34 | .md-expansion-panel-icon svg {
35 | fill: #DDD;
36 | }
37 | }
38 |
39 | &:not(.md-open) {
40 | &:not([disabled]) {
41 | &:focus,
42 | &:focus md-expansion-panel-collapsed {
43 | background: #EEE;
44 | }
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "angular-material-expansion-panel",
3 | "version": "0.7.2",
4 | "description": "Material Design Expansion Panels.",
5 | "main": [
6 | "dist/md-expansion-panel.js",
7 | "dist/md-expansion-panel.css"
8 | ],
9 | "repository": {
10 | "type": "git",
11 | "url": "git://github.com/B-3PO/angular-material-expansion-panel.git"
12 | },
13 | "authors": [
14 | "Ben Rubin"
15 | ],
16 | "license": "MIT",
17 | "keywords": [
18 | "material",
19 | "material-design",
20 | "design",
21 | "angular",
22 | "component",
23 | "expansion",
24 | "panel",
25 | "panels"
26 | ],
27 | "ignore": [
28 | "**/.*",
29 | "node_modules",
30 | "bower_components",
31 | "app",
32 | "src",
33 | "gulp"
34 | ],
35 | "dependencies": {
36 | "angular": "^1.5.7",
37 | "angular-animate": "^1.5.7",
38 | "angular-messages": "^1.5.7",
39 | "angular-aria": "^1.5.7",
40 | "angular-material": "^1.1.0"
41 | },
42 | "devDependencies": {
43 | "angular-mocks": "^1.5.7",
44 | "angular-route": "^1.5.7"
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 Ben Rubin
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/gulp/indexBuild.js:
--------------------------------------------------------------------------------
1 | var paths = require('./config').paths;
2 |
3 | var gulp = require('gulp');
4 | var inject = require('gulp-inject');
5 | var mainBowerFiles = require('gulp-main-bower-files');
6 |
7 |
8 | exports.inject = function () {
9 | var scripts = gulp.src(paths.scripts, {read: false});
10 | var appScripts = gulp.src(paths.appScripts, {read: false});
11 | var appCss = gulp.src(paths.appCss, {read: false});
12 | var bower = gulp.src(paths.bower).pipe(mainBowerFiles({includeDev: true}));
13 | var css = gulp.src(paths.injectCss, {read: false});
14 |
15 | return gulp.src(paths.app + 'index.html')
16 | .pipe(inject(css, {
17 | name: 'css',
18 | relative: true,
19 | ignorePath: '../public'
20 | }))
21 | .pipe(inject(scripts, {
22 | name: 'scripts',
23 | relative: true,
24 | ignorePath: '../src'
25 | }))
26 | .pipe(inject(appScripts, {
27 | name: 'appscripts',
28 | relative: true,
29 | ignorePath: '../'
30 | }))
31 | .pipe(inject(bower, {
32 | name: 'bower',
33 | relative: true,
34 | ignorePath: '../bower_components/'
35 | }))
36 | .pipe(gulp.dest(paths.dest));
37 | };
38 |
--------------------------------------------------------------------------------
/gulp/cssBuild.js:
--------------------------------------------------------------------------------
1 | var paths = require('./config').paths;
2 |
3 | var gulp = require('gulp');
4 | var gutil = require('gulp-util');
5 | var autoprefixer = require('gulp-autoprefixer');
6 | var gulpFilter = require('gulp-filter');
7 | var concat = require('gulp-concat');
8 | var cssnano = require('gulp-cssnano');
9 | var sass = require('gulp-sass');
10 | var rename = require('gulp-rename');
11 |
12 | exports.getDev = function (srcs) {
13 | srcs = srcs || paths.css.concat(paths.appCss);
14 |
15 | return function dev() {
16 | return gulp.src(srcs)
17 | .pipe(sass())
18 | .pipe(autoprefixer())
19 | .pipe(gulp.dest(paths.dest))
20 | .on('end', function(){
21 | gutil.log(gutil.colors.green('✔ CSS dev'), 'Finished');
22 | });
23 | };
24 | };
25 |
26 |
27 | exports.release = function () {
28 | return gulp.src(paths.css)
29 | .pipe(sass())
30 | .pipe(concat('md-expansion-panel.css'))
31 | .pipe(autoprefixer())
32 | .pipe(gulp.dest(paths.build))
33 | .pipe(cssnano({zindex: false}))
34 | .pipe(rename('md-expansion-panel.min.css'))
35 | .pipe(gulp.dest(paths.build))
36 | .on('end', function(){
37 | gutil.log(gutil.colors.green('✔ CSS Build'), 'Finished');
38 | });
39 | };
40 |
--------------------------------------------------------------------------------
/docs/expansionPanels-theme.css:
--------------------------------------------------------------------------------
1 | md-expansion-panel {
2 | background: #FFF; }
3 | md-expansion-panel md-expansion-panel-collapsed,
4 | md-expansion-panel .md-expansion-panel-footer-container,
5 | md-expansion-panel .md-expansion-panel-header-container {
6 | background: #FFF; }
7 | md-expansion-panel md-expansion-panel-collapsed .md-title,
8 | md-expansion-panel md-expansion-panel-collapsed .md-summary,
9 | md-expansion-panel .md-expansion-panel-footer-container .md-title,
10 | md-expansion-panel .md-expansion-panel-footer-container .md-summary,
11 | md-expansion-panel .md-expansion-panel-header-container .md-title,
12 | md-expansion-panel .md-expansion-panel-header-container .md-summary {
13 | color: #333; }
14 | md-expansion-panel md-expansion-panel-footer .md-expansion-panel-footer-container,
15 | md-expansion-panel md-expansion-panel-header .md-expansion-panel-header-container {
16 | border-color: #DDD; }
17 | md-expansion-panel .md-expansion-panel-icon svg {
18 | fill: #999; }
19 | md-expansion-panel[disabled] md-expansion-panel-collapsed {
20 | color: #DDD; }
21 | md-expansion-panel:not(.md-open):not([disabled]):focus,
22 | md-expansion-panel:not(.md-open):not([disabled]):focus md-expansion-panel-collapsed {
23 | background: #EEE; }
24 |
--------------------------------------------------------------------------------
/src/js/expansionPanel.service.js:
--------------------------------------------------------------------------------
1 | angular
2 | .module('material.components.expansionPanels')
3 | .factory('$mdExpansionPanel', expansionPanelService);
4 |
5 |
6 | /**
7 | * @ngdoc service
8 | * @name $mdExpansionPanel
9 | * @module material.components.expansionPanels
10 | *
11 | * @description
12 | * Expand and collapse Expansion Panel using its `md-component-id`
13 | *
14 | * @example
15 | * $mdExpansionPanel('comonentId').then(function (instance) {
16 | * instance.exapand();
17 | * instance.collapse({animation: false});
18 | * instance.remove({animation: false});
19 | * instance.onRemove(function () {});
20 | * });
21 | */
22 | expansionPanelService.$inject = ['$mdComponentRegistry', '$mdUtil', '$log'];
23 | function expansionPanelService($mdComponentRegistry, $mdUtil, $log) {
24 | var errorMsg = "ExpansionPanel '{0}' is not available! Did you use md-component-id='{0}'?";
25 | var service = {
26 | find: findInstance,
27 | waitFor: waitForInstance
28 | };
29 |
30 | return function (handle) {
31 | if (handle === undefined) { return service; }
32 | return findInstance(handle);
33 | };
34 |
35 |
36 |
37 | function findInstance(handle) {
38 | var instance = $mdComponentRegistry.get(handle);
39 |
40 | if (!instance) {
41 | // Report missing instance
42 | $log.error( $mdUtil.supplant(errorMsg, [handle || ""]) );
43 | return undefined;
44 | }
45 |
46 | return instance;
47 | }
48 |
49 | function waitForInstance(handle) {
50 | return $mdComponentRegistry.when(handle).catch($log.error);
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/app/pages/autoExpand/autoExpand.controller.js:
--------------------------------------------------------------------------------
1 | angular
2 | .module('angularMaterialExpansionPanel')
3 | .controller('AutoExpandController', AutoExpandController);
4 |
5 |
6 |
7 | AutoExpandController.$inject = ['$mdExpansionPanelGroup'];
8 | function AutoExpandController($mdExpansionPanelGroup) {
9 | var vm = this;
10 |
11 | var groupInstance;
12 |
13 | vm.title = 'Panel Title';
14 | vm.summary = 'Panel Summary text';
15 | vm.content = 'Many were increasingly of the opinion that they’d all made a big mistake in coming down from the trees in the first place. And some said that even the trees had been a bad move, and that no one should ever have left the oceans.';
16 |
17 | vm.addTemplated = addTemplated;
18 |
19 | $mdExpansionPanelGroup().waitFor('expansionPanelGroup').then(function (instance) {
20 | groupInstance = instance;
21 |
22 | instance.register('templated', {
23 | templateUrl: 'pages/group/panels/templated/templated.html',
24 | controller: 'TemplatedPanelController',
25 | controllerAs: 'vm'
26 | });
27 |
28 | instance.add({
29 | templateUrl: 'pages/group/panels/one/one.html',
30 | controller: 'OnePanelController',
31 | controllerAs: 'vm'
32 | });
33 | });
34 |
35 | function addTemplated() {
36 | groupInstance.add('templated', {
37 | title: vm.title,
38 | summary: vm.summary,
39 | content: vm.content
40 | }).then(function (panel) {
41 | // panel.expand().then(function () {
42 | // console.log('opened post animation');
43 | // });
44 | });
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/docs/js/expansionPanel.service.js:
--------------------------------------------------------------------------------
1 | (function(){"use strict";angular
2 | .module('material.components.expansionPanels')
3 | .factory('$mdExpansionPanel', expansionPanelService);
4 |
5 |
6 | /**
7 | * @ngdoc service
8 | * @name $mdExpansionPanel
9 | * @module material.components.expansionPanels
10 | *
11 | * @description
12 | * Expand and collapse Expansion Panel using its `md-component-id`
13 | *
14 | * @example
15 | * $mdExpansionPanel('comonentId').then(function (instance) {
16 | * instance.exapand();
17 | * instance.collapse({animation: false});
18 | * instance.remove({animation: false});
19 | * instance.onRemove(function () {});
20 | * });
21 | */
22 | expansionPanelService.$inject = ['$mdComponentRegistry', '$mdUtil', '$log'];
23 | function expansionPanelService($mdComponentRegistry, $mdUtil, $log) {
24 | var errorMsg = "ExpansionPanel '{0}' is not available! Did you use md-component-id='{0}'?";
25 | var service = {
26 | find: findInstance,
27 | waitFor: waitForInstance
28 | };
29 |
30 | return function (handle) {
31 | if (handle === undefined) { return service; }
32 | return findInstance(handle);
33 | };
34 |
35 |
36 |
37 | function findInstance(handle) {
38 | var instance = $mdComponentRegistry.get(handle);
39 |
40 | if (!instance) {
41 | // Report missing instance
42 | $log.error( $mdUtil.supplant(errorMsg, [handle || ""]) );
43 | return undefined;
44 | }
45 |
46 | return instance;
47 | }
48 |
49 | function waitForInstance(handle) {
50 | return $mdComponentRegistry.when(handle).catch($log.error);
51 | }
52 | }
53 | }());
--------------------------------------------------------------------------------
/docs/pages/autoExpand/autoExpand.controller.js:
--------------------------------------------------------------------------------
1 | (function(){"use strict";angular
2 | .module('angularMaterialExpansionPanel')
3 | .controller('AutoExpandController', AutoExpandController);
4 |
5 |
6 |
7 | AutoExpandController.$inject = ['$mdExpansionPanelGroup'];
8 | function AutoExpandController($mdExpansionPanelGroup) {
9 | var vm = this;
10 |
11 | var groupInstance;
12 |
13 | vm.title = 'Panel Title';
14 | vm.summary = 'Panel Summary text';
15 | vm.content = 'Many were increasingly of the opinion that they’d all made a big mistake in coming down from the trees in the first place. And some said that even the trees had been a bad move, and that no one should ever have left the oceans.';
16 |
17 | vm.addTemplated = addTemplated;
18 |
19 | $mdExpansionPanelGroup().waitFor('expansionPanelGroup').then(function (instance) {
20 | groupInstance = instance;
21 |
22 | instance.register('templated', {
23 | templateUrl: 'pages/group/panels/templated/templated.html',
24 | controller: 'TemplatedPanelController',
25 | controllerAs: 'vm'
26 | });
27 |
28 | instance.add({
29 | templateUrl: 'pages/group/panels/one/one.html',
30 | controller: 'OnePanelController',
31 | controllerAs: 'vm'
32 | });
33 | });
34 |
35 | function addTemplated() {
36 | groupInstance.add('templated', {
37 | title: vm.title,
38 | summary: vm.summary,
39 | content: vm.content
40 | }).then(function (panel) {
41 | // panel.expand().then(function () {
42 | // console.log('opened post animation');
43 | // });
44 | });
45 | }
46 | }
47 | }());
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "angular-material-expansion-panel",
3 | "version": "0.7.2",
4 | "author": "Ben Rubin",
5 | "description": "Material Design Expansion Panels for angular material",
6 | "keywords": "material, material-design, design, angular, component, expansion, panel, panels",
7 | "license": "MIT",
8 | "repository": {
9 | "type": "git",
10 | "url": "git://github.com/B-3PO/angular-material-expansion-panel.git"
11 | },
12 | "main": "index.js",
13 | "devDependencies": {
14 | "bump": "^0.2.5",
15 | "del": "^2.2.0",
16 | "gulp": "^3.9.1",
17 | "gulp-angular-templatecache": "^1.9.1",
18 | "gulp-autoprefixer": "^3.1.0",
19 | "gulp-bump": "^1.0.0",
20 | "gulp-concat": "^2.6.0",
21 | "gulp-cssnano": "^2.1.0",
22 | "gulp-filter": "^4.0.0",
23 | "gulp-flatten": "^0.3.0",
24 | "gulp-if": "^2.0.1",
25 | "gulp-inject": "^4.0.0",
26 | "gulp-jasmine": "^2.4.0",
27 | "gulp-jshint": "^2.0.0",
28 | "gulp-main-bower-files": "^1.5.1",
29 | "gulp-ng-constant": "^1.1.0",
30 | "gulp-preprocess": "^2.0.0",
31 | "gulp-rename": "^1.2.2",
32 | "gulp-sass": "^2.3.2",
33 | "gulp-sequence": "^0.4.5",
34 | "gulp-serve": "^1.2.0",
35 | "gulp-strip-debug": "^1.1.0",
36 | "gulp-uglify": "^1.5.3",
37 | "gulp-util": "^3.0.7",
38 | "gulp-wrap": "^0.11.0",
39 | "jshint": "^2.8.0",
40 | "karma": "^1.1.0",
41 | "karma-jasmine": "^1.0.2",
42 | "karma-phantomjs-launcher": "^1.0.1",
43 | "karma-spec-reporter": "0.0.26"
44 | },
45 | "scripts": {
46 | "local": "gulp",
47 | "build": "gulp build"
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/app/pages/multiple/multiple.controller.js:
--------------------------------------------------------------------------------
1 | angular
2 | .module('angularMaterialExpansionPanel')
3 | .controller('MultipleController', MultipleController);
4 |
5 |
6 |
7 | MultipleController.$inject = ['$mdExpansionPanelGroup'];
8 | function MultipleController($mdExpansionPanelGroup) {
9 | var vm = this;
10 |
11 | var groupInstance;
12 |
13 | vm.title = 'Panel Title';
14 | vm.summary = 'Panel Summary text';
15 | vm.content = 'Many were increasingly of the opinion that they’d all made a big mistake in coming down from the trees in the first place. And some said that even the trees had been a bad move, and that no one should ever have left the oceans.';
16 |
17 | vm.addTemplated = addTemplated;
18 |
19 | $mdExpansionPanelGroup().waitFor('expansionPanelGroup').then(function (instance) {
20 | groupInstance = instance;
21 |
22 | instance.register('templated', {
23 | templateUrl: 'pages/group/panels/templated/templated.html',
24 | controller: 'TemplatedPanelController',
25 | controllerAs: 'vm'
26 | });
27 |
28 | instance.add({
29 | templateUrl: 'pages/group/panels/one/one.html',
30 | controller: 'OnePanelController',
31 | controllerAs: 'vm'
32 | }).then(function (panelInstance) {
33 | panelInstance.expand();
34 | });
35 | });
36 |
37 | function addTemplated() {
38 | groupInstance.add('templated', {
39 | title: vm.title,
40 | summary: vm.summary,
41 | content: vm.content
42 | }).then(function (panel) {
43 | // panel.expand().then(function () {
44 | // console.log('opened post animation');
45 | // });
46 | });
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/docs/pages/multiple/multiple.controller.js:
--------------------------------------------------------------------------------
1 | (function(){"use strict";angular
2 | .module('angularMaterialExpansionPanel')
3 | .controller('MultipleController', MultipleController);
4 |
5 |
6 |
7 | MultipleController.$inject = ['$mdExpansionPanelGroup'];
8 | function MultipleController($mdExpansionPanelGroup) {
9 | var vm = this;
10 |
11 | var groupInstance;
12 |
13 | vm.title = 'Panel Title';
14 | vm.summary = 'Panel Summary text';
15 | vm.content = 'Many were increasingly of the opinion that they’d all made a big mistake in coming down from the trees in the first place. And some said that even the trees had been a bad move, and that no one should ever have left the oceans.';
16 |
17 | vm.addTemplated = addTemplated;
18 |
19 | $mdExpansionPanelGroup().waitFor('expansionPanelGroup').then(function (instance) {
20 | groupInstance = instance;
21 |
22 | instance.register('templated', {
23 | templateUrl: 'pages/group/panels/templated/templated.html',
24 | controller: 'TemplatedPanelController',
25 | controllerAs: 'vm'
26 | });
27 |
28 | instance.add({
29 | templateUrl: 'pages/group/panels/one/one.html',
30 | controller: 'OnePanelController',
31 | controllerAs: 'vm'
32 | }).then(function (panelInstance) {
33 | panelInstance.expand();
34 | });
35 | });
36 |
37 | function addTemplated() {
38 | groupInstance.add('templated', {
39 | title: vm.title,
40 | summary: vm.summary,
41 | content: vm.content
42 | }).then(function (panel) {
43 | // panel.expand().then(function () {
44 | // console.log('opened post animation');
45 | // });
46 | });
47 | }
48 | }
49 | }());
--------------------------------------------------------------------------------
/app/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Angular Material Test
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 | Panels
28 | Groups
29 | Auto Expand
30 | Multiple
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/app/pages/autoExpand/autoExpand.html:
--------------------------------------------------------------------------------
1 | Group With Auto Expand
2 |
3 |
4 |
5 | Expansion Panel Groups with the auto-expand attribute will expand when added to the group
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
54 |
--------------------------------------------------------------------------------
/docs/pages/autoExpand/autoExpand.html:
--------------------------------------------------------------------------------
1 | Group With Auto Expand
2 |
3 |
4 |
5 | Expansion Panel Groups with the auto-expand attribute will expand when added to the group
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
40 |
41 |
42 |
43 | Content
44 |
45 |
48 |
49 |
50 |
51 | Add Panel
52 |
53 |
54 |
--------------------------------------------------------------------------------
/app/pages/multiple/multiple.html:
--------------------------------------------------------------------------------
1 | Group with Multiple
2 |
3 |
4 |
5 | Expansion Panel Groups with the mulitple attribute allow for more than 1 panel to be expanded at the same time
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
40 |
41 |
42 |
43 | Content
44 |
45 |
48 |
49 |
50 |
51 | Add Panel
52 |
53 |
54 |
--------------------------------------------------------------------------------
/docs/pages/multiple/multiple.html:
--------------------------------------------------------------------------------
1 | Group with Multiple
2 |
3 |
4 |
5 | Expansion Panel Groups with the mulitple attribute allow for more than 1 panel to be expanded at the same time
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
40 |
41 |
42 |
43 | Content
44 |
45 |
48 |
49 |
50 |
51 | Add Panel
52 |
53 |
54 |
--------------------------------------------------------------------------------
/app/pages/group/group.html:
--------------------------------------------------------------------------------
1 | Group
2 |
3 |
4 | Expansion Panel Groups allow you to controll a set of panels. You can add panels using templates and controllers. You can also register panels to add by a given name; and you can pass in locals.
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
39 |
40 |
41 |
42 | Content
43 |
44 |
47 |
48 |
49 |
50 | Add Panel
51 |
52 |
53 |
--------------------------------------------------------------------------------
/docs/pages/group/group.html:
--------------------------------------------------------------------------------
1 | Group
2 |
3 |
4 | Expansion Panel Groups allow you to controll a set of panels. You can add panels using templates and controllers. You can also register panels to add by a given name; and you can pass in locals.
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
39 |
40 |
41 |
42 | Content
43 |
44 |
47 |
48 |
49 |
50 | Add Panel
51 |
52 |
53 |
--------------------------------------------------------------------------------
/app/pages/group/group.controller.js:
--------------------------------------------------------------------------------
1 | angular
2 | .module('angularMaterialExpansionPanel')
3 | .controller('GroupController', GroupController);
4 |
5 |
6 |
7 | GroupController.$inject = ['$mdExpansionPanelGroup'];
8 | function GroupController($mdExpansionPanelGroup) {
9 | var vm = this;
10 |
11 | var groupInstance;
12 |
13 | vm.title = 'Panel Title';
14 | vm.summary = 'Panel Summary text';
15 | vm.content = 'Many were increasingly of the opinion that they’d all made a big mistake in coming down from the trees in the first place. And some said that even the trees had been a bad move, and that no one should ever have left the oceans.';
16 |
17 | vm.addTemplated = addTemplated;
18 |
19 | $mdExpansionPanelGroup().waitFor('expansionPanelGroup').then(function (instance) {
20 | groupInstance = instance;
21 |
22 | instance.register('templated', {
23 | templateUrl: 'pages/group/panels/templated/templated.html',
24 | controller: 'TemplatedPanelController',
25 | controllerAs: 'vm'
26 | });
27 |
28 | instance.add({
29 | templateUrl: 'pages/group/panels/one/one.html',
30 | controller: 'OnePanelController',
31 | controllerAs: 'vm'
32 | }).then(function (panelInstance) {
33 | panelInstance.expand();
34 | });
35 |
36 | var change = instance.onChange(function (count) {
37 | console.log('panel count', count);
38 | });
39 |
40 |
41 | setTimeout(function () {
42 | change();
43 | }, 10000);
44 | });
45 |
46 | function addTemplated() {
47 | groupInstance.add('templated', {
48 | title: vm.title,
49 | summary: vm.summary,
50 | content: vm.content
51 | }).then(function (panel) {
52 | panel.onRemove(function () {
53 | console.log('panel removed');
54 | });
55 | });
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/docs/pages/group/group.controller.js:
--------------------------------------------------------------------------------
1 | (function(){"use strict";angular
2 | .module('angularMaterialExpansionPanel')
3 | .controller('GroupController', GroupController);
4 |
5 |
6 |
7 | GroupController.$inject = ['$mdExpansionPanelGroup'];
8 | function GroupController($mdExpansionPanelGroup) {
9 | var vm = this;
10 |
11 | var groupInstance;
12 |
13 | vm.title = 'Panel Title';
14 | vm.summary = 'Panel Summary text';
15 | vm.content = 'Many were increasingly of the opinion that they’d all made a big mistake in coming down from the trees in the first place. And some said that even the trees had been a bad move, and that no one should ever have left the oceans.';
16 |
17 | vm.addTemplated = addTemplated;
18 |
19 | $mdExpansionPanelGroup().waitFor('expansionPanelGroup').then(function (instance) {
20 | groupInstance = instance;
21 |
22 | instance.register('templated', {
23 | templateUrl: 'pages/group/panels/templated/templated.html',
24 | controller: 'TemplatedPanelController',
25 | controllerAs: 'vm'
26 | });
27 |
28 | instance.add({
29 | templateUrl: 'pages/group/panels/one/one.html',
30 | controller: 'OnePanelController',
31 | controllerAs: 'vm'
32 | }).then(function (panelInstance) {
33 | panelInstance.expand();
34 | });
35 |
36 | var change = instance.onChange(function (count) {
37 | console.log('panel count', count);
38 | });
39 |
40 |
41 | setTimeout(function () {
42 | change();
43 | }, 10000);
44 | });
45 |
46 | function addTemplated() {
47 | groupInstance.add('templated', {
48 | title: vm.title,
49 | summary: vm.summary,
50 | content: vm.content
51 | }).then(function (panel) {
52 | panel.onRemove(function () {
53 | console.log('panel removed');
54 | });
55 | });
56 | }
57 | }
58 | }());
--------------------------------------------------------------------------------
/gulp/jsBuild.js:
--------------------------------------------------------------------------------
1 | var paths = require('./config').paths;
2 |
3 | var gulp = require('gulp');
4 | var jshint = require('gulp-jshint');
5 | var wrap = require("gulp-wrap");
6 | var concat = require('gulp-concat');
7 | var uglify = require('gulp-uglify');
8 | var stripDebug = require('gulp-strip-debug');
9 | var rename = require("gulp-rename");
10 | var filter = require('gulp-filter');
11 | var gutil = require('gulp-util');
12 |
13 |
14 |
15 | exports.getDevSrc = function (srcs) {
16 | srcs = srcs || paths.scripts;
17 |
18 | return function dev() {
19 | return gulp.src(srcs, {base: paths.src})
20 | .pipe(wrap('(function(){"use strict";<%= contents %>}());'))
21 | .pipe(jshint())
22 | .pipe(jshint.reporter('default'))
23 | .pipe(gulp.dest(paths.dest))
24 | .on('end', function() {
25 | gutil.log(gutil.colors.green('✔ JS Dev'), 'Finished');
26 | });
27 | };
28 | }
29 |
30 |
31 | exports.getDevApp = function (srcs) {
32 | srcs = srcs || paths.appScripts;
33 |
34 | return function dev() {
35 | return gulp.src(srcs, {base: paths.app})
36 | .pipe(wrap('(function(){"use strict";<%= contents %>}());'))
37 | .pipe(jshint())
38 | .pipe(jshint.reporter('default'))
39 | .pipe(gulp.dest(paths.dest))
40 | .on('end', function() {
41 | gutil.log(gutil.colors.green('✔ JS Dev'), 'Finished');
42 | });
43 | };
44 | }
45 |
46 |
47 | exports.release = function () {
48 | return gulp.src(paths.scripts)
49 | .pipe(wrap('(function(){"use strict";<%= contents %>}());'))
50 | .pipe(jshint())
51 | .pipe(jshint.reporter('default'))
52 | .pipe(concat('md-expansion-panel.js'))
53 | .pipe(stripDebug())
54 | .pipe(gulp.dest(paths.build))
55 | .pipe(uglify())
56 | .pipe(rename('md-expansion-panel.min.js'))
57 | .pipe(gulp.dest(paths.build))
58 | .on('end', function() {
59 | gutil.log(gutil.colors.green('✔ JS build'), 'Finished');
60 | });
61 | }
62 |
--------------------------------------------------------------------------------
/karma.conf.js:
--------------------------------------------------------------------------------
1 | // Karma configuration
2 | // Generated on Wed May 11 2016 11:02:59 GMT-0500 (CDT)
3 | module.exports = function(config) {
4 | config.set({
5 |
6 | // base path that will be used to resolve all patterns (eg. files, exclude)
7 | basePath: '',
8 |
9 |
10 | // frameworks to use
11 | // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
12 | frameworks: ['jasmine'],
13 |
14 |
15 | // list of files / patterns to load in the browser
16 | files: [
17 | 'dist/md-expansion-panel.css',
18 | 'bower_components/angular-material/angular-material.css',
19 |
20 | 'bower_components/angular/angular.js',
21 | 'bower_components/angular-animate/angular-animate.js',
22 | 'bower_components/angular-material/angular-material.js',
23 | 'bower_components/angular-mocks/angular-mocks.js',
24 | 'src/expansionPanels.js',
25 | 'src/**/*.js'
26 | ],
27 |
28 |
29 | // test results reporter to use
30 | // possible values: 'dots', 'progress'
31 | // available reporters: https://npmjs.org/browse/keyword/karma-reporter
32 | reporters: [ 'progress'],
33 |
34 |
35 | // web server port
36 | port: 9876,
37 |
38 |
39 | // enable / disable colors in the output (reporters and logs)
40 | colors: true,
41 |
42 |
43 | // level of logging
44 | // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
45 | logLevel: config.LOG_INFO,
46 |
47 |
48 | // enable / disable watching file and executing tests whenever any file changes
49 | autoWatch: true,
50 |
51 |
52 | // start these browsers
53 | // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
54 | // browsers: ['Chrome'],
55 | browsers: ['PhantomJS'],
56 |
57 |
58 | // Continuous Integration mode
59 | // if true, Karma captures browsers, runs the tests and exits
60 | singleRun: false,
61 |
62 | // Concurrency level
63 | // how many browser should be started simultaneous
64 | concurrency: Infinity
65 | })
66 | }
67 |
--------------------------------------------------------------------------------
/src/js/expansionPanelFooter.directive.js:
--------------------------------------------------------------------------------
1 | angular
2 | .module('material.components.expansionPanels')
3 | .directive('mdExpansionPanelFooter', expansionPanelFooterDirective);
4 |
5 |
6 |
7 |
8 | /**
9 | * @ngdoc directive
10 | * @name mdExpansionPanelFooter
11 | * @module material.components.expansionPanels
12 | *
13 | * @restrict E
14 | *
15 | * @description
16 | * `mdExpansionPanelFooter` is nested inside of `mdExpansionPanelExpanded` and contains content you want at the bottom.
17 | * By default the Footer will stick to the bottom of the page if the panel expands past
18 | * this is optional
19 | *
20 | * @param {boolean=} md-no-sticky - add this aatribute to disable sticky
21 | **/
22 | function expansionPanelFooterDirective() {
23 | var directive = {
24 | restrict: 'E',
25 | transclude: true,
26 | template: '',
27 | require: '^^mdExpansionPanel',
28 | link: link
29 | };
30 | return directive;
31 |
32 |
33 |
34 | function link(scope, element, attrs, expansionPanelCtrl) {
35 | var isStuck = false;
36 | var noSticky = attrs.mdNoSticky !== undefined;
37 | var container = angular.element(element[0].querySelector('.md-expansion-panel-footer-container'));
38 |
39 | expansionPanelCtrl.registerFooter({
40 | show: show,
41 | hide: hide,
42 | onScroll: onScroll,
43 | onResize: onResize,
44 | noSticky: noSticky
45 | });
46 |
47 |
48 |
49 | function show() {
50 |
51 | }
52 | function hide() {
53 | unstick();
54 | }
55 |
56 | function onScroll(top, bottom, transformTop) {
57 | var height;
58 | var footerBounds = element[0].getBoundingClientRect();
59 | var offset;
60 |
61 | if (footerBounds.bottom > bottom) {
62 | height = container[0].offsetHeight;
63 | offset = bottom - height - transformTop;
64 | if (offset < element[0].parentNode.getBoundingClientRect().top) {
65 | offset = element[0].parentNode.getBoundingClientRect().top;
66 | }
67 |
68 | // set container width because element becomes postion fixed
69 | container.css('width', expansionPanelCtrl.$element[0].offsetWidth + 'px');
70 |
71 | // set element height so it does not loose its height when container is position fixed
72 | element.css('height', height + 'px');
73 | container.css('top', offset + 'px');
74 |
75 | element.addClass('md-stick');
76 | isStuck = true;
77 | } else if (isStuck === true) {
78 | unstick();
79 | }
80 | }
81 |
82 | function onResize(width) {
83 | if (isStuck === false) { return; }
84 | container.css('width', width + 'px');
85 | }
86 |
87 |
88 | function unstick() {
89 | isStuck = false;
90 | container.css('width', '');
91 | container.css('top', '');
92 | element.css('height', '');
93 | element.removeClass('md-stick');
94 | }
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/src/js/expansionPanelHeader.directive.js:
--------------------------------------------------------------------------------
1 | angular
2 | .module('material.components.expansionPanels')
3 | .directive('mdExpansionPanelHeader', expansionPanelHeaderDirective);
4 |
5 |
6 |
7 | /**
8 | * @ngdoc directive
9 | * @name mdExpansionPanelHeader
10 | * @module material.components.expansionPanels
11 | *
12 | * @restrict E
13 | *
14 | * @description
15 | * `mdExpansionPanelHeader` is nested inside of `mdExpansionPanelExpanded` and contains content you want in place of the collapsed content
16 | * this is optional
17 | *
18 | * @param {boolean=} md-no-sticky - add this aatribute to disable sticky
19 | **/
20 | expansionPanelHeaderDirective.$inject = [];
21 | function expansionPanelHeaderDirective() {
22 | var directive = {
23 | restrict: 'E',
24 | transclude: true,
25 | template: '',
26 | require: '^^mdExpansionPanel',
27 | link: link
28 | };
29 | return directive;
30 |
31 |
32 |
33 | function link(scope, element, attrs, expansionPanelCtrl) {
34 | var isStuck = false;
35 | var noSticky = attrs.mdNoSticky !== undefined;
36 | var container = angular.element(element[0].querySelector('.md-expansion-panel-header-container'));
37 |
38 | expansionPanelCtrl.registerHeader({
39 | show: show,
40 | hide: hide,
41 | noSticky: noSticky,
42 | onScroll: onScroll,
43 | onResize: onResize
44 | });
45 |
46 |
47 | function show() {
48 |
49 | }
50 | function hide() {
51 | unstick();
52 | }
53 |
54 |
55 | function onScroll(top, bottom, transformTop) {
56 | var offset;
57 | var panelbottom;
58 | var bounds = element[0].getBoundingClientRect();
59 |
60 |
61 | if (bounds.top < top) {
62 | offset = top - transformTop;
63 | panelbottom = element[0].parentNode.getBoundingClientRect().bottom - top - bounds.height;
64 | if (panelbottom < 0) {
65 | offset += panelbottom;
66 | }
67 |
68 | // set container width because element becomes postion fixed
69 | container.css('width', element[0].offsetWidth + 'px');
70 | container.css('top', offset + 'px');
71 |
72 | // set element height so it does not shink when container is position fixed
73 | element.css('height', container[0].offsetHeight + 'px');
74 |
75 | element.removeClass('md-no-stick');
76 | element.addClass('md-stick');
77 | isStuck = true;
78 | } else if (isStuck === true) {
79 | unstick();
80 | }
81 | }
82 |
83 | function onResize(width) {
84 | if (isStuck === false) { return; }
85 | container.css('width', width + 'px');
86 | }
87 |
88 |
89 | function unstick() {
90 | isStuck = false;
91 | container.css('width', '');
92 | element.css('height', '');
93 | element.css('top', '');
94 | element.removeClass('md-stick');
95 | element.addClass('md-no-stick');
96 | }
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/docs/js/expansionPanelFooter.directive.js:
--------------------------------------------------------------------------------
1 | (function(){"use strict";angular
2 | .module('material.components.expansionPanels')
3 | .directive('mdExpansionPanelFooter', expansionPanelFooterDirective);
4 |
5 |
6 |
7 |
8 | /**
9 | * @ngdoc directive
10 | * @name mdExpansionPanelFooter
11 | * @module material.components.expansionPanels
12 | *
13 | * @restrict E
14 | *
15 | * @description
16 | * `mdExpansionPanelFooter` is nested inside of `mdExpansionPanelExpanded` and contains content you want at the bottom.
17 | * By default the Footer will stick to the bottom of the page if the panel expands past
18 | * this is optional
19 | *
20 | * @param {boolean=} md-no-sticky - add this aatribute to disable sticky
21 | **/
22 | function expansionPanelFooterDirective() {
23 | var directive = {
24 | restrict: 'E',
25 | transclude: true,
26 | template: '',
27 | require: '^^mdExpansionPanel',
28 | link: link
29 | };
30 | return directive;
31 |
32 |
33 |
34 | function link(scope, element, attrs, expansionPanelCtrl) {
35 | var isStuck = false;
36 | var noSticky = attrs.mdNoSticky !== undefined;
37 | var container = angular.element(element[0].querySelector('.md-expansion-panel-footer-container'));
38 |
39 | expansionPanelCtrl.registerFooter({
40 | show: show,
41 | hide: hide,
42 | onScroll: onScroll,
43 | onResize: onResize,
44 | noSticky: noSticky
45 | });
46 |
47 |
48 |
49 | function show() {
50 |
51 | }
52 | function hide() {
53 | unstick();
54 | }
55 |
56 | function onScroll(top, bottom, transformTop) {
57 | var height;
58 | var footerBounds = element[0].getBoundingClientRect();
59 | var offset;
60 |
61 | if (footerBounds.bottom > bottom) {
62 | height = container[0].offsetHeight;
63 | offset = bottom - height - transformTop;
64 | if (offset < element[0].parentNode.getBoundingClientRect().top) {
65 | offset = element[0].parentNode.getBoundingClientRect().top;
66 | }
67 |
68 | // set container width because element becomes postion fixed
69 | container.css('width', expansionPanelCtrl.$element[0].offsetWidth + 'px');
70 |
71 | // set element height so it does not loose its height when container is position fixed
72 | element.css('height', height + 'px');
73 | container.css('top', offset + 'px');
74 |
75 | element.addClass('md-stick');
76 | isStuck = true;
77 | } else if (isStuck === true) {
78 | unstick();
79 | }
80 | }
81 |
82 | function onResize(width) {
83 | if (isStuck === false) { return; }
84 | container.css('width', width + 'px');
85 | }
86 |
87 |
88 | function unstick() {
89 | isStuck = false;
90 | container.css('width', '');
91 | container.css('top', '');
92 | element.css('height', '');
93 | element.removeClass('md-stick');
94 | }
95 | }
96 | }
97 | }());
--------------------------------------------------------------------------------
/docs/js/expansionPanelHeader.directive.js:
--------------------------------------------------------------------------------
1 | (function(){"use strict";angular
2 | .module('material.components.expansionPanels')
3 | .directive('mdExpansionPanelHeader', expansionPanelHeaderDirective);
4 |
5 |
6 |
7 | /**
8 | * @ngdoc directive
9 | * @name mdExpansionPanelHeader
10 | * @module material.components.expansionPanels
11 | *
12 | * @restrict E
13 | *
14 | * @description
15 | * `mdExpansionPanelHeader` is nested inside of `mdExpansionPanelExpanded` and contains content you want in place of the collapsed content
16 | * this is optional
17 | *
18 | * @param {boolean=} md-no-sticky - add this aatribute to disable sticky
19 | **/
20 | expansionPanelHeaderDirective.$inject = [];
21 | function expansionPanelHeaderDirective() {
22 | var directive = {
23 | restrict: 'E',
24 | transclude: true,
25 | template: '',
26 | require: '^^mdExpansionPanel',
27 | link: link
28 | };
29 | return directive;
30 |
31 |
32 |
33 | function link(scope, element, attrs, expansionPanelCtrl) {
34 | var isStuck = false;
35 | var noSticky = attrs.mdNoSticky !== undefined;
36 | var container = angular.element(element[0].querySelector('.md-expansion-panel-header-container'));
37 |
38 | expansionPanelCtrl.registerHeader({
39 | show: show,
40 | hide: hide,
41 | noSticky: noSticky,
42 | onScroll: onScroll,
43 | onResize: onResize
44 | });
45 |
46 |
47 | function show() {
48 |
49 | }
50 | function hide() {
51 | unstick();
52 | }
53 |
54 |
55 | function onScroll(top, bottom, transformTop) {
56 | var offset;
57 | var panelbottom;
58 | var bounds = element[0].getBoundingClientRect();
59 |
60 |
61 | if (bounds.top < top) {
62 | offset = top - transformTop;
63 | panelbottom = element[0].parentNode.getBoundingClientRect().bottom - top - bounds.height;
64 | if (panelbottom < 0) {
65 | offset += panelbottom;
66 | }
67 |
68 | // set container width because element becomes postion fixed
69 | container.css('width', element[0].offsetWidth + 'px');
70 | container.css('top', offset + 'px');
71 |
72 | // set element height so it does not shink when container is position fixed
73 | element.css('height', container[0].offsetHeight + 'px');
74 |
75 | element.removeClass('md-no-stick');
76 | element.addClass('md-stick');
77 | isStuck = true;
78 | } else if (isStuck === true) {
79 | unstick();
80 | }
81 | }
82 |
83 | function onResize(width) {
84 | if (isStuck === false) { return; }
85 | container.css('width', width + 'px');
86 | }
87 |
88 |
89 | function unstick() {
90 | isStuck = false;
91 | container.css('width', '');
92 | element.css('height', '');
93 | element.css('top', '');
94 | element.removeClass('md-stick');
95 | element.addClass('md-no-stick');
96 | }
97 | }
98 | }
99 | }());
--------------------------------------------------------------------------------
/src/js/expansionPanelCollapsed.directive.js:
--------------------------------------------------------------------------------
1 | angular
2 | .module('material.components.expansionPanels')
3 | .directive('mdExpansionPanelCollapsed', expansionPanelCollapsedDirective);
4 |
5 |
6 |
7 | /**
8 | * @ngdoc directive
9 | * @name mdExpansionPanelCollapsed
10 | * @module material.components.expansionPanels
11 | *
12 | * @restrict E
13 | *
14 | * @description
15 | * `mdExpansionPanelCollapsed` is used to contain content when the panel is collapsed
16 | **/
17 | expansionPanelCollapsedDirective.$inject = ['$animateCss', '$timeout'];
18 | function expansionPanelCollapsedDirective($animateCss, $timeout) {
19 | var directive = {
20 | restrict: 'E',
21 | require: '^^mdExpansionPanel',
22 | link: link
23 | };
24 | return directive;
25 |
26 |
27 | function link(scope, element, attrs, expansionPanelCtrl) {
28 | expansionPanelCtrl.registerCollapsed({
29 | show: show,
30 | hide: hide
31 | });
32 |
33 |
34 | element.on('click', function () {
35 | expansionPanelCtrl.expand();
36 | });
37 |
38 |
39 | function hide(options) {
40 | // set width to maintian demensions when element is set to postion: absolute
41 | element.css('width', element[0].offsetWidth + 'px');
42 | // set min height so the expansion panel does not shrink when collapsed element is set to position: absolute
43 | expansionPanelCtrl.$element.css('min-height', element[0].offsetHeight + 'px');
44 |
45 | var animationParams = {
46 | addClass: 'md-absolute md-hide',
47 | from: {opacity: 1},
48 | to: {opacity: 0}
49 | };
50 | if (options.animation === false) { animationParams.duration = 0; }
51 | $animateCss(element, animationParams)
52 | .start()
53 | .then(function () {
54 | element.removeClass('md-hide');
55 | element.css('display', 'none');
56 | });
57 | }
58 |
59 |
60 | function show(options) {
61 | element.css('display', '');
62 | // set width to maintian demensions when element is set to postion: absolute
63 | element.css('width', element[0].parentNode.offsetWidth + 'px');
64 |
65 | var animationParams = {
66 | addClass: 'md-show',
67 | from: {opacity: 0},
68 | to: {opacity: 1}
69 | };
70 | if (options.animation === false) { animationParams.duration = 0; }
71 | $animateCss(element, animationParams)
72 | .start()
73 | .then(function () {
74 | // safari will animate the min-height if transition is not set to 0
75 | expansionPanelCtrl.$element.css('transition', 'none');
76 | element.removeClass('md-absolute md-show');
77 |
78 | // remove width when element is no longer position: absolute
79 | element.css('width', '');
80 |
81 |
82 | // remove min height when element is no longer position: absolute
83 | expansionPanelCtrl.$element.css('min-height', '');
84 | // remove transition block on next digest
85 | $timeout(function () {
86 | expansionPanelCtrl.$element.css('transition', '');
87 | }, 0);
88 | });
89 | }
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/docs/js/expansionPanelCollapsed.directive.js:
--------------------------------------------------------------------------------
1 | (function(){"use strict";angular
2 | .module('material.components.expansionPanels')
3 | .directive('mdExpansionPanelCollapsed', expansionPanelCollapsedDirective);
4 |
5 |
6 |
7 | /**
8 | * @ngdoc directive
9 | * @name mdExpansionPanelCollapsed
10 | * @module material.components.expansionPanels
11 | *
12 | * @restrict E
13 | *
14 | * @description
15 | * `mdExpansionPanelCollapsed` is used to contain content when the panel is collapsed
16 | **/
17 | expansionPanelCollapsedDirective.$inject = ['$animateCss', '$timeout'];
18 | function expansionPanelCollapsedDirective($animateCss, $timeout) {
19 | var directive = {
20 | restrict: 'E',
21 | require: '^^mdExpansionPanel',
22 | link: link
23 | };
24 | return directive;
25 |
26 |
27 | function link(scope, element, attrs, expansionPanelCtrl) {
28 | expansionPanelCtrl.registerCollapsed({
29 | show: show,
30 | hide: hide
31 | });
32 |
33 |
34 | element.on('click', function () {
35 | expansionPanelCtrl.expand();
36 | });
37 |
38 |
39 | function hide(options) {
40 | // set width to maintian demensions when element is set to postion: absolute
41 | element.css('width', element[0].offsetWidth + 'px');
42 | // set min height so the expansion panel does not shrink when collapsed element is set to position: absolute
43 | expansionPanelCtrl.$element.css('min-height', element[0].offsetHeight + 'px');
44 |
45 | var animationParams = {
46 | addClass: 'md-absolute md-hide',
47 | from: {opacity: 1},
48 | to: {opacity: 0}
49 | };
50 | if (options.animation === false) { animationParams.duration = 0; }
51 | $animateCss(element, animationParams)
52 | .start()
53 | .then(function () {
54 | element.removeClass('md-hide');
55 | element.css('display', 'none');
56 | });
57 | }
58 |
59 |
60 | function show(options) {
61 | element.css('display', '');
62 | // set width to maintian demensions when element is set to postion: absolute
63 | element.css('width', element[0].parentNode.offsetWidth + 'px');
64 |
65 | var animationParams = {
66 | addClass: 'md-show',
67 | from: {opacity: 0},
68 | to: {opacity: 1}
69 | };
70 | if (options.animation === false) { animationParams.duration = 0; }
71 | $animateCss(element, animationParams)
72 | .start()
73 | .then(function () {
74 | // safari will animate the min-height if transition is not set to 0
75 | expansionPanelCtrl.$element.css('transition', 'none');
76 | element.removeClass('md-absolute md-show');
77 |
78 | // remove width when element is no longer position: absolute
79 | element.css('width', '');
80 |
81 |
82 | // remove min height when element is no longer position: absolute
83 | expansionPanelCtrl.$element.css('min-height', '');
84 | // remove transition block on next digest
85 | $timeout(function () {
86 | expansionPanelCtrl.$element.css('transition', '');
87 | }, 0);
88 | });
89 | }
90 | }
91 | }
92 | }());
--------------------------------------------------------------------------------
/src/js/expansionPanelExpanded.directive.js:
--------------------------------------------------------------------------------
1 | angular
2 | .module('material.components.expansionPanels')
3 | .directive('mdExpansionPanelExpanded', expansionPanelExpandedDirective);
4 |
5 |
6 |
7 | /**
8 | * @ngdoc directive
9 | * @name mdExpansionPanelExpanded
10 | * @module material.components.expansionPanels
11 | *
12 | * @restrict E
13 | *
14 | * @description
15 | * `mdExpansionPanelExpanded` is used to contain content when the panel is expanded
16 | *
17 | * @param {number=} height - add this aatribute set the max height of the expanded content. The container will be set to scroll
18 | **/
19 | expansionPanelExpandedDirective.$inject = ['$animateCss', '$timeout'];
20 | function expansionPanelExpandedDirective($animateCss, $timeout) {
21 | var directive = {
22 | restrict: 'E',
23 | require: '^^mdExpansionPanel',
24 | link: link
25 | };
26 | return directive;
27 |
28 |
29 | function link(scope, element, attrs, expansionPanelCtrl) {
30 | var setHeight = attrs.height || undefined;
31 | if (setHeight !== undefined) { setHeight = setHeight.replace('px', '') + 'px'; }
32 |
33 | expansionPanelCtrl.registerExpanded({
34 | show: show,
35 | hide: hide,
36 | setHeight: setHeight !== undefined,
37 | $element: element
38 | });
39 |
40 |
41 |
42 |
43 | function hide(options) {
44 | var height = setHeight ? setHeight : element[0].scrollHeight + 'px';
45 | element.addClass('md-hide md-overflow');
46 | element.removeClass('md-show md-scroll-y');
47 |
48 | var animationParams = {
49 | from: {'max-height': height, opacity: 1},
50 | to: {'max-height': '48px', opacity: 0}
51 | };
52 | if (options.animation === false) { animationParams.duration = 0; }
53 | $animateCss(element, animationParams)
54 | .start()
55 | .then(function () {
56 | element.css('display', 'none');
57 | element.removeClass('md-hide');
58 | });
59 | }
60 |
61 |
62 | function show(options) {
63 | element.css('display', '');
64 | element.addClass('md-show md-overflow');
65 | // use passed in height or the contents height
66 | var height = setHeight ? setHeight : element[0].scrollHeight + 'px';
67 |
68 | var animationParams = {
69 | from: {'max-height': '48px', opacity: 0},
70 | to: {'max-height': height, opacity: 1}
71 | };
72 | if (options.animation === false) { animationParams.duration = 0; }
73 | $animateCss(element, animationParams)
74 | .start()
75 | .then(function () {
76 |
77 | // if height was passed in then set div to scroll
78 | if (setHeight !== undefined) {
79 | element.addClass('md-scroll-y');
80 | } else {
81 | // safari will animate the max-height if transition is not set to 0
82 | element.css('transition', 'none');
83 | element.css('max-height', 'none');
84 | // remove transition block on next digest
85 | $timeout(function () {
86 | element.css('transition', '');
87 | }, 0);
88 | }
89 |
90 | element.removeClass('md-overflow');
91 | });
92 | }
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/docs/js/expansionPanelExpanded.directive.js:
--------------------------------------------------------------------------------
1 | (function(){"use strict";angular
2 | .module('material.components.expansionPanels')
3 | .directive('mdExpansionPanelExpanded', expansionPanelExpandedDirective);
4 |
5 |
6 |
7 | /**
8 | * @ngdoc directive
9 | * @name mdExpansionPanelExpanded
10 | * @module material.components.expansionPanels
11 | *
12 | * @restrict E
13 | *
14 | * @description
15 | * `mdExpansionPanelExpanded` is used to contain content when the panel is expanded
16 | *
17 | * @param {number=} height - add this aatribute set the max height of the expanded content. The container will be set to scroll
18 | **/
19 | expansionPanelExpandedDirective.$inject = ['$animateCss', '$timeout'];
20 | function expansionPanelExpandedDirective($animateCss, $timeout) {
21 | var directive = {
22 | restrict: 'E',
23 | require: '^^mdExpansionPanel',
24 | link: link
25 | };
26 | return directive;
27 |
28 |
29 | function link(scope, element, attrs, expansionPanelCtrl) {
30 | var setHeight = attrs.height || undefined;
31 | if (setHeight !== undefined) { setHeight = setHeight.replace('px', '') + 'px'; }
32 |
33 | expansionPanelCtrl.registerExpanded({
34 | show: show,
35 | hide: hide,
36 | setHeight: setHeight !== undefined,
37 | $element: element
38 | });
39 |
40 |
41 |
42 |
43 | function hide(options) {
44 | var height = setHeight ? setHeight : element[0].scrollHeight + 'px';
45 | element.addClass('md-hide md-overflow');
46 | element.removeClass('md-show md-scroll-y');
47 |
48 | var animationParams = {
49 | from: {'max-height': height, opacity: 1},
50 | to: {'max-height': '48px', opacity: 0}
51 | };
52 | if (options.animation === false) { animationParams.duration = 0; }
53 | $animateCss(element, animationParams)
54 | .start()
55 | .then(function () {
56 | element.css('display', 'none');
57 | element.removeClass('md-hide');
58 | });
59 | }
60 |
61 |
62 | function show(options) {
63 | element.css('display', '');
64 | element.addClass('md-show md-overflow');
65 | // use passed in height or the contents height
66 | var height = setHeight ? setHeight : element[0].scrollHeight + 'px';
67 |
68 | var animationParams = {
69 | from: {'max-height': '48px', opacity: 0},
70 | to: {'max-height': height, opacity: 1}
71 | };
72 | if (options.animation === false) { animationParams.duration = 0; }
73 | $animateCss(element, animationParams)
74 | .start()
75 | .then(function () {
76 |
77 | // if height was passed in then set div to scroll
78 | if (setHeight !== undefined) {
79 | element.addClass('md-scroll-y');
80 | } else {
81 | // safari will animate the max-height if transition is not set to 0
82 | element.css('transition', 'none');
83 | element.css('max-height', 'none');
84 | // remove transition block on next digest
85 | $timeout(function () {
86 | element.css('transition', '');
87 | }, 0);
88 | }
89 |
90 | element.removeClass('md-overflow');
91 | });
92 | }
93 | }
94 | }
95 | }());
--------------------------------------------------------------------------------
/docs/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Angular Material Test
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 | Panels
56 | Groups
57 | Auto Expand
58 | Multiple
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
77 |
78 |
79 |
80 |
--------------------------------------------------------------------------------
/docs/pages/home/home.html:
--------------------------------------------------------------------------------
1 | Panels
2 |
3 |
4 |
5 | Expansion Panels have an collapsed section and a expanded section. Optionally you can add a header and footer to the expanded sections. By default bothe the header and footer will stick to the tops and bottoms of the md-content container they are in, but you can disable that.
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | Title
18 | Summary
19 |
20 |
21 |
22 |
23 |
24 |
25 | Expanded Title
26 | Expanded Summary
27 |
28 |
29 |
30 |
31 | Content
32 | Put content in here
33 |
34 |
35 |
36 |
37 | Collapse
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | Sticky
50 | header and footer will stick
51 |
52 |
53 |
54 |
55 |
56 |
57 | Sticky
58 | header and footer will stick
59 |
60 |
61 |
62 | Content
63 | Put content in here
64 |
65 | Content
66 | Put content in here
67 |
68 | Content
69 | Put content in here
70 |
71 | Content
72 | Put content in here
73 |
74 | Content
75 | Put content in here
76 |
77 | Content
78 | Put content in here
79 |
80 | Content
81 | Put content in here
82 |
83 | Content
84 | Put content in here
85 |
86 | Content
87 | Put content in here
88 |
89 |
90 |
91 |
92 | Collapse
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 | No Sticky
106 | header and footer sticky disabled
107 |
108 |
109 |
110 |
111 |
112 | No Sticky
113 | header and footer sticky disabled
114 |
115 |
116 |
117 | Content
118 | Put content in here
119 |
120 | Content
121 | Put content in here
122 |
123 | Content
124 | Put content in here
125 |
126 | Content
127 | Put content in here
128 |
129 | Content
130 | Put content in here
131 |
132 | Content
133 | Put content in here
134 |
135 | Content
136 | Put content in here
137 |
138 | Content
139 | Put content in here
140 |
141 | Content
142 | Put content in here
143 |
144 |
145 |
146 |
147 | Collapse
148 |
149 |
150 |
151 |
152 |
153 |
--------------------------------------------------------------------------------
/gulpfile.js:
--------------------------------------------------------------------------------
1 | var paths = require('./gulp/config').paths;
2 |
3 | var gulp = require('gulp');
4 | var serve = require('gulp-serve');
5 | var gulpSequence = require('gulp-sequence');
6 | var del = require('del');
7 | var bump = require('gulp-bump');
8 | var templateCache = require('gulp-angular-templatecache');
9 | var KarmaServer = require('karma').Server;
10 |
11 |
12 | var jsBuild = require('./gulp/jsBuild');
13 | var cssBuild = require('./gulp/cssBuild');
14 | var indexBuild = require('./gulp/indexBuild');
15 |
16 |
17 |
18 | gulp.task('jsSrcBuild', jsBuild.getDevSrc());
19 | gulp.task('jsAppBuild', jsBuild.getDevApp());
20 | gulp.task('jsReleaseBuild', jsBuild.release);
21 | gulp.task('cssBuild', cssBuild.getDev());
22 | gulp.task('cssReleaseBuild', cssBuild.release);
23 | gulp.task('indexBuild', indexBuild.inject);
24 |
25 |
26 |
27 | // -- main tasks. use these to watch and build and release
28 |
29 | gulp.task('default', gulpSequence('buildLocal', ['serve', 'watch']));
30 | gulp.task('buildLocal', gulpSequence(
31 | 'clean',
32 | [
33 | 'jsSrcBuild',
34 | 'jsAppBuild',
35 | 'cssBuild',
36 | 'copyPartials',
37 | 'copyIcons'
38 | ],
39 | 'indexBuild'
40 | ));
41 |
42 | gulp.task('build', gulpSequence('buildIconCache', ['jsReleaseBuild', 'cssReleaseBuild'], 'cleanIconCache'));
43 | gulp.task('docs', gulpSequence(
44 | 'buildLocal',
45 | 'copyPublicToDocs',
46 | 'copyBowerToDocs'
47 | ));
48 |
49 | gulp.task('copyPublicToDocs', function () {
50 | return gulp.src('public/**/*')
51 | .pipe(gulp.dest('docs/'));
52 | });
53 |
54 | gulp.task('copyBowerToDocs', function () {
55 | return gulp.src('bower_components/**/*')
56 | .pipe(gulp.dest('docs/'));
57 | });
58 |
59 |
60 |
61 | gulp.task('clean', function () {
62 | return del(paths.dest);
63 | });
64 |
65 |
66 | gulp.task('copyPartials', function () {
67 | return gulp.src(paths.partials, {base: paths.app})
68 | .pipe(gulp.dest(paths.dest));
69 | });
70 |
71 | gulp.task('copyIcons', function () {
72 | return gulp.src(paths.icons, {base: paths.src})
73 | .pipe(gulp.dest(paths.dest));
74 | });
75 |
76 | gulp.task('buildIconCache', function () {
77 | return gulp.src(paths.icons)
78 | .pipe(templateCache({module: 'material.components.expansionPanels'}))
79 | .pipe(gulp.dest(paths.src));
80 | });
81 |
82 | gulp.task('cleanIconCache', function () {
83 | return del('src/templates.js');
84 | });
85 |
86 | gulp.task('serve', serve({
87 | root: ['public', 'bower_components'],
88 | port: 8080
89 | }));
90 |
91 |
92 |
93 | gulp.task('test-karma', function (done) {
94 | new KarmaServer({
95 | configFile: __dirname + '/karma.conf.js',
96 | singleRun: true
97 | }, function (errorCode) {
98 | if (errorCode !== 0) {
99 | console.log('Karma exited with error code ' + errorCode);
100 | done();
101 | return process.exit(errorCode);
102 | }
103 | done();
104 | }).start();
105 | });
106 |
107 | gulp.task('test', gulpSequence('build', 'test-karma'));
108 |
109 |
110 |
111 |
112 | gulp.task('watch', function () {
113 | gulp.watch(paths.scripts, function (event) {
114 | jsBuild.getDevSrc(event.path)()
115 | .on('end', function () {
116 | if (event.type !== 'changed') { indexBuild.inject(); }
117 | });
118 | });
119 |
120 | gulp.watch(paths.appScripts, function (event) {
121 | jsBuild.getDevApp(event.path)()
122 | .on('end', function () {
123 | if (event.type !== 'changed') { indexBuild.inject(); }
124 | });
125 | });
126 |
127 |
128 | gulp.watch(paths.css.concat(paths.appCss), function (event) {
129 | cssBuild.getDev(event.path)()
130 | .on('end', function () {
131 | if (event.type !== 'changed') { indexBuild.inject(); }
132 | });
133 | });
134 |
135 |
136 | gulp.watch(paths.partials, function (event) {
137 | return gulp.src(event.path, {base: paths.app})
138 | .pipe(gulp.dest(paths.dest));
139 | });
140 | });
141 |
142 |
143 |
144 |
145 |
146 |
147 | gulp.task('major', function(){
148 | gulp.src(['./bower.json', './package.json'])
149 | .pipe(bump({type:'major'}))
150 | .pipe(gulp.dest('./'));
151 | });
152 |
153 | gulp.task('minor', function(){
154 | gulp.src(['./bower.json', './package.json'])
155 | .pipe(bump({type:'minor'}))
156 | .pipe(gulp.dest('./'));
157 | });
158 |
159 | gulp.task('patch', function(){
160 | gulp.src(['./bower.json', './package.json'])
161 | .pipe(bump({type:'patch'}))
162 | .pipe(gulp.dest('./'));
163 | });
164 |
165 | gulp.task('prerelease', function(){
166 | gulp.src(['./bower.json', './package.json'])
167 | .pipe(bump({type:'prerelease'}))
168 | .pipe(gulp.dest('./'));
169 | });
170 |
--------------------------------------------------------------------------------
/src/js/expansionPanelGroup.directive.js:
--------------------------------------------------------------------------------
1 | angular
2 | .module('material.components.expansionPanels')
3 | .directive('mdExpansionPanelGroup', expansionPanelGroupDirective);
4 |
5 | /**
6 | * @ngdoc directive
7 | * @name mdExpansionPanelGroup
8 | * @module material.components.expansionPanels
9 | *
10 | * @restrict E
11 | *
12 | * @description
13 | * `mdExpansionPanelGroup` is a container used to manage multiple expansion panels
14 | *
15 | * @param {string=} md-component-id - add an id if you want to acces the panel via the `$mdExpansionPanelGroup` service
16 | * @param {string=} auto-expand - panels expand when added to ``
17 | * @param {string=} multiple - allows for more than one panel to be expanded at a time
18 | **/
19 | function expansionPanelGroupDirective() {
20 | var directive = {
21 | restrict: 'E',
22 | controller: ['$scope', '$attrs', '$element', '$mdComponentRegistry', controller]
23 | };
24 | return directive;
25 |
26 |
27 | function controller($scope, $attrs, $element, $mdComponentRegistry) {
28 | /* jshint validthis: true */
29 | var vm = this;
30 |
31 | var deregister;
32 | var registered = {};
33 | var panels = {};
34 | var onChangeFuncs = [];
35 | var multipleExpand = $attrs.mdMultiple !== undefined || $attrs.multiple !== undefined;
36 | var autoExpand = $attrs.mdAutoExpand !== undefined || $attrs.autoExpand !== undefined;
37 |
38 |
39 | deregister = $mdComponentRegistry.register({
40 | $element: $element,
41 | register: register,
42 | getRegistered: getRegistered,
43 | getAll: getAll,
44 | getOpen: getOpen,
45 | remove: remove,
46 | removeAll: removeAll,
47 | collapseAll: collapseAll,
48 | onChange: onChange,
49 | count: panelCount
50 | }, $attrs.mdComponentId);
51 |
52 | vm.addPanel = addPanel;
53 | vm.expandPanel = expandPanel;
54 | vm.removePanel = removePanel;
55 |
56 |
57 | $scope.$on('$destroy', function () {
58 | if (typeof deregister === 'function') {
59 | deregister();
60 | deregister = undefined;
61 | }
62 |
63 | // destroy all panels
64 | // for some reason the child panels scopes are not getting destroyed
65 | Object.keys(panels).forEach(function (key) {
66 | panels[key].destroy();
67 | });
68 | });
69 |
70 |
71 |
72 | function onChange(callback) {
73 | onChangeFuncs.push(callback);
74 |
75 | return function () {
76 | onChangeFuncs.splice(onChangeFuncs.indexOf(callback), 1);
77 | };
78 | }
79 |
80 | function callOnChange() {
81 | var count = panelCount();
82 | onChangeFuncs.forEach(function (func) {
83 | func(count);
84 | });
85 | }
86 |
87 |
88 | function addPanel(componentId, panelCtrl) {
89 | panels[componentId] = panelCtrl;
90 | if (autoExpand === true) {
91 | panelCtrl.expand();
92 | closeOthers(componentId);
93 | }
94 | callOnChange();
95 | }
96 |
97 | function expandPanel(componentId) {
98 | closeOthers(componentId);
99 | }
100 |
101 | function remove(componentId, options) {
102 | return panels[componentId].remove(options);
103 | }
104 |
105 | function removeAll(options) {
106 | Object.keys(panels).forEach(function (panelId) {
107 | panels[panelId].remove(options);
108 | });
109 | }
110 |
111 | function removePanel(componentId) {
112 | delete panels[componentId];
113 | callOnChange();
114 | }
115 |
116 | function panelCount() {
117 | return Object.keys(panels).length;
118 | }
119 |
120 | function closeOthers(id) {
121 | if (multipleExpand === false) {
122 | Object.keys(panels).forEach(function (panelId) {
123 | if (panelId !== id) { panels[panelId].collapse(); }
124 | });
125 | }
126 | }
127 |
128 |
129 | function register(name, options) {
130 | if (registered[name] !== undefined) {
131 | throw Error('$mdExpansionPanelGroup.register() The name "' + name + '" has already been registered');
132 | }
133 | registered[name] = options;
134 | }
135 |
136 |
137 | function getRegistered(name) {
138 | if (registered[name] === undefined) {
139 | throw Error('$mdExpansionPanelGroup.addPanel() Cannot find Panel with name of "' + name + '"');
140 | }
141 | return registered[name];
142 | }
143 |
144 |
145 | function getAll() {
146 | return Object.keys(panels).map(function (panelId) {
147 | return panels[panelId];
148 | });
149 | }
150 |
151 | function getOpen() {
152 | return Object.keys(panels).map(function (panelId) {
153 | return panels[panelId];
154 | }).filter(function (instance) {
155 | return instance.isOpen();
156 | });
157 | }
158 |
159 | function collapseAll(noAnimation) {
160 | var animation = noAnimation === true ? false : true;
161 | Object.keys(panels).forEach(function (panelId) {
162 | panels[panelId].collapse({animation: animation});
163 | });
164 | }
165 | }
166 | }
167 |
--------------------------------------------------------------------------------
/docs/js/expansionPanelGroup.directive.js:
--------------------------------------------------------------------------------
1 | (function(){"use strict";angular
2 | .module('material.components.expansionPanels')
3 | .directive('mdExpansionPanelGroup', expansionPanelGroupDirective);
4 |
5 | /**
6 | * @ngdoc directive
7 | * @name mdExpansionPanelGroup
8 | * @module material.components.expansionPanels
9 | *
10 | * @restrict E
11 | *
12 | * @description
13 | * `mdExpansionPanelGroup` is a container used to manage multiple expansion panels
14 | *
15 | * @param {string=} md-component-id - add an id if you want to acces the panel via the `$mdExpansionPanelGroup` service
16 | * @param {string=} auto-expand - panels expand when added to ``
17 | * @param {string=} multiple - allows for more than one panel to be expanded at a time
18 | **/
19 | function expansionPanelGroupDirective() {
20 | var directive = {
21 | restrict: 'E',
22 | controller: ['$scope', '$attrs', '$element', '$mdComponentRegistry', controller]
23 | };
24 | return directive;
25 |
26 |
27 | function controller($scope, $attrs, $element, $mdComponentRegistry) {
28 | /* jshint validthis: true */
29 | var vm = this;
30 |
31 | var deregister;
32 | var registered = {};
33 | var panels = {};
34 | var onChangeFuncs = [];
35 | var multipleExpand = $attrs.mdMultiple !== undefined || $attrs.multiple !== undefined;
36 | var autoExpand = $attrs.mdAutoExpand !== undefined || $attrs.autoExpand !== undefined;
37 |
38 |
39 | deregister = $mdComponentRegistry.register({
40 | $element: $element,
41 | register: register,
42 | getRegistered: getRegistered,
43 | getAll: getAll,
44 | getOpen: getOpen,
45 | remove: remove,
46 | removeAll: removeAll,
47 | collapseAll: collapseAll,
48 | onChange: onChange,
49 | count: panelCount
50 | }, $attrs.mdComponentId);
51 |
52 | vm.addPanel = addPanel;
53 | vm.expandPanel = expandPanel;
54 | vm.removePanel = removePanel;
55 |
56 |
57 | $scope.$on('$destroy', function () {
58 | if (typeof deregister === 'function') {
59 | deregister();
60 | deregister = undefined;
61 | }
62 |
63 | // destroy all panels
64 | // for some reason the child panels scopes are not getting destroyed
65 | Object.keys(panels).forEach(function (key) {
66 | panels[key].destroy();
67 | });
68 | });
69 |
70 |
71 |
72 | function onChange(callback) {
73 | onChangeFuncs.push(callback);
74 |
75 | return function () {
76 | onChangeFuncs.splice(onChangeFuncs.indexOf(callback), 1);
77 | };
78 | }
79 |
80 | function callOnChange() {
81 | var count = panelCount();
82 | onChangeFuncs.forEach(function (func) {
83 | func(count);
84 | });
85 | }
86 |
87 |
88 | function addPanel(componentId, panelCtrl) {
89 | panels[componentId] = panelCtrl;
90 | if (autoExpand === true) {
91 | panelCtrl.expand();
92 | closeOthers(componentId);
93 | }
94 | callOnChange();
95 | }
96 |
97 | function expandPanel(componentId) {
98 | closeOthers(componentId);
99 | }
100 |
101 | function remove(componentId, options) {
102 | return panels[componentId].remove(options);
103 | }
104 |
105 | function removeAll(options) {
106 | Object.keys(panels).forEach(function (panelId) {
107 | panels[panelId].remove(options);
108 | });
109 | }
110 |
111 | function removePanel(componentId) {
112 | delete panels[componentId];
113 | callOnChange();
114 | }
115 |
116 | function panelCount() {
117 | return Object.keys(panels).length;
118 | }
119 |
120 | function closeOthers(id) {
121 | if (multipleExpand === false) {
122 | Object.keys(panels).forEach(function (panelId) {
123 | if (panelId !== id) { panels[panelId].collapse(); }
124 | });
125 | }
126 | }
127 |
128 |
129 | function register(name, options) {
130 | if (registered[name] !== undefined) {
131 | throw Error('$mdExpansionPanelGroup.register() The name "' + name + '" has already been registered');
132 | }
133 | registered[name] = options;
134 | }
135 |
136 |
137 | function getRegistered(name) {
138 | if (registered[name] === undefined) {
139 | throw Error('$mdExpansionPanelGroup.addPanel() Cannot find Panel with name of "' + name + '"');
140 | }
141 | return registered[name];
142 | }
143 |
144 |
145 | function getAll() {
146 | return Object.keys(panels).map(function (panelId) {
147 | return panels[panelId];
148 | });
149 | }
150 |
151 | function getOpen() {
152 | return Object.keys(panels).map(function (panelId) {
153 | return panels[panelId];
154 | }).filter(function (instance) {
155 | return instance.isOpen();
156 | });
157 | }
158 |
159 | function collapseAll(noAnimation) {
160 | var animation = noAnimation === true ? false : true;
161 | Object.keys(panels).forEach(function (panelId) {
162 | panels[panelId].collapse({animation: animation});
163 | });
164 | }
165 | }
166 | }
167 | }());
--------------------------------------------------------------------------------
/app/pages/home/home.html:
--------------------------------------------------------------------------------
1 | Panels
2 |
3 |
4 |
5 | Expansion Panels have an collapsed section and a expanded section. Optionally you can add a header and footer to the expanded sections. By default bothe the header and footer will stick to the tops and bottoms of the md-content container they are in, but you can disable that.
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | Title
18 | Summary
19 |
20 |
21 |
22 |
23 |
24 |
25 | Expanded Title
26 | Expanded Summary
27 |
28 |
29 |
30 |
31 | Content
32 | Put content in here
33 |
34 |
35 |
36 |
37 | Collapse
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | Sticky
50 | header and footer will stick
51 |
52 |
53 |
54 |
55 |
56 |
57 | Sticky
58 | header and footer will stick
59 |
60 |
61 |
62 | Content
63 | Put content in here
64 |
65 | Content
66 | Put content in here
67 |
68 | Content
69 | Put content in here
70 |
71 | Content
72 | Put content in here
73 |
74 | Content
75 | Put content in here
76 |
77 | Content
78 | Put content in here
79 |
80 | Content
81 | Put content in here
82 |
83 | Content
84 | Put content in here
85 |
86 | Content
87 | Put content in here
88 |
89 |
90 |
91 |
92 | Collapse
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 | No Sticky
106 | header and footer sticky disabled
107 |
108 |
109 |
110 |
111 |
112 | No Sticky
113 | header and footer sticky disabled
114 |
115 |
116 |
117 | Content
118 | Put content in here
119 |
120 | Content
121 | Put content in here
122 |
123 | Content
124 | Put content in here
125 |
126 | Content
127 | Put content in here
128 |
129 | Content
130 | Put content in here
131 |
132 | Content
133 | Put content in here
134 |
135 | Content
136 | Put content in here
137 |
138 | Content
139 | Put content in here
140 |
141 | Content
142 | Put content in here
143 |
144 |
145 |
146 |
147 | Collapse
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 | Disabled Panel
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 | Disabled Panel
168 | Expanded Summary
169 |
170 |
171 |
172 |
173 | Content
174 | Put content in here
175 |
176 |
177 |
178 |
179 | Collapse
180 |
181 |
182 |
183 |
184 |
185 |
--------------------------------------------------------------------------------
/src/expansionPanels.scss:
--------------------------------------------------------------------------------
1 | .layout-padding > md-expansion-panel-group {
2 | padding: 0;
3 | }
4 |
5 | /* --- Expansion Panel --- */
6 |
7 | md-expansion-panel {
8 | display: block;
9 | position: relative;
10 | outline: none;
11 | margin-top: 0;
12 | margin-bottom: 0;
13 | padding: 0;
14 | box-shadow: 0 -1px 0 #e5e5e5,
15 | 0 0 2px rgba(0,0,0,.12),
16 | 0 2px 4px rgba(0,0,0,.24);
17 |
18 |
19 | &.md-open {
20 | margin-top: 16px;
21 | margin-bottom: 16px;
22 |
23 | &:first-of-type {
24 | margin-top: 0;
25 | }
26 | }
27 |
28 | &.md-close {
29 | overflow: hidden;
30 | }
31 |
32 | &:not(.md-no-animation) {
33 | &.md-open {
34 | transition: margin-top 0.12s cubic-bezier(0.25, 0.8, 0.25, 1),
35 | margin-bottom 0.12s cubic-bezier(0.25, 0.8, 0.25, 1);
36 | }
37 |
38 | &.md-close {
39 | transition: margin-top 0.08s cubic-bezier(0.25, 0.8, 0.25, 1),
40 | margin-bottom 0.08s cubic-bezier(0.25, 0.8, 0.25, 1);
41 | }
42 | }
43 | }
44 |
45 |
46 |
47 |
48 |
49 | md-expansion-panel-collapsed .md-title,
50 | md-expansion-panel-header .md-title {
51 | flex: 1;
52 | font-size: 16px;
53 | font-weight: 600;
54 | min-width: 80px;
55 | max-width: 184px;
56 | overflow: hidden;
57 | text-overflow: ellipsis;
58 | text-align: left;
59 | white-space: nowrap;
60 | }
61 |
62 | md-expansion-panel-collapsed .md-summary,
63 | md-expansion-panel-header .md-summary {
64 | flex: 1;
65 | font-size: 13px;
66 | overflow: hidden;
67 | text-overflow: ellipsis;
68 | text-align: left;
69 | white-space: nowrap;
70 | }
71 |
72 |
73 |
74 | /* --- Expansion Panel Collapsed ---- */
75 |
76 | md-expansion-panel {
77 | md-expansion-panel-collapsed {
78 | display: flex;
79 | min-height: 48px;
80 | line-height: 48px;
81 | padding: 0 24px;
82 | opacity: 1;
83 | z-index: 2;
84 | box-sizing: border-box;
85 |
86 |
87 | &.md-absolute {
88 | position: absolute;
89 | }
90 |
91 | &.md-hide {
92 | opacity: 0;
93 | }
94 | }
95 |
96 | &:not(.md-no-animation) {
97 | md-expansion-panel-collapsed {
98 | &.md-show {
99 | transition: opacity 0.03s linear;
100 | }
101 |
102 | &.md-hide {
103 | transition: opacity 0.1s cubic-bezier(0.25, 0.8, 0.25, 1);
104 | }
105 | }
106 | }
107 | }
108 |
109 |
110 |
111 |
112 | /* --- Expansion Panel Expanded --- */
113 |
114 | md-expansion-panel {
115 | md-expansion-panel-expanded {
116 | display: none;
117 | min-height: 48px;
118 |
119 |
120 | &.md-show,
121 | &.md-hide {
122 | display: block;
123 | }
124 |
125 | &.md-scroll-y {
126 | overflow-y: auto;
127 | }
128 |
129 | &.md-overflow {
130 | overflow: hidden
131 | }
132 |
133 |
134 | md-expansion-panel-content {
135 | display: block;
136 | padding: 16px 24px;
137 | }
138 | }
139 |
140 | &:not(.md-no-animation) {
141 | md-expansion-panel-expanded {
142 | &.md-show {
143 | transition: max-height 0.12s cubic-bezier(0.25, 0.8, 0.25, 1),
144 | opacity 0.12s cubic-bezier(0.25, 0.8, 0.25, 1);
145 | }
146 |
147 | &.md-hide {
148 | transition: max-height 0.06s cubic-bezier(0.25, 0.8, 0.25, 1),
149 | opacity 0.06s cubic-bezier(0.25, 0.8, 0.25, 1);
150 | }
151 | }
152 | }
153 | }
154 |
155 |
156 |
157 | /* --- Expansion Panel Header --- */
158 |
159 | md-expansion-panel-header {
160 | display: block;
161 | position: relative;
162 | outline: none;
163 |
164 |
165 | .md-expansion-panel-header-container {
166 | display: flex;
167 | min-height: 48px;
168 | line-height: 48px;
169 | padding: 0 24px;
170 | box-sizing: border-box;
171 | border-bottom: 1px solid;
172 | align-items: center;
173 | }
174 |
175 | &.md-stick {
176 | .md-expansion-panel-header-container {
177 | position: fixed;
178 | z-index: 2;
179 | animation: panelBodyHeaderStickyHoverIn 0.3s ease-out both;
180 | }
181 | }
182 |
183 | &.md-no-stick {
184 | .md-expansion-panel-header-container {
185 | animation: panelBodyHeaderStickyHoverOut 0.3s ease-out both;
186 | }
187 | }
188 | }
189 |
190 |
191 |
192 |
193 | /* --- Expansion Panel Footer --- */
194 |
195 |
196 | md-expansion-panel-footer {
197 | display: block;
198 | position: relative;
199 |
200 | &.md-show,
201 | &.md-hide {
202 | display: block;
203 | }
204 |
205 |
206 | .md-expansion-panel-footer-container {
207 | display: flex;
208 | min-height: 48px;
209 | line-height: 48px;
210 | padding: 0 24px;
211 | border-top: 1px solid;
212 | box-sizing: border-box;
213 | }
214 |
215 |
216 | &.md-stick {
217 | .md-expansion-panel-footer-container {
218 | position: fixed;
219 | z-index: 2;
220 | }
221 | }
222 | }
223 |
224 |
225 |
226 |
227 | /* --- expand icon --- */
228 |
229 | md-expansion-panel {
230 | &:not(.md-no-animation) {
231 | .md-expansion-panel-icon {
232 | transition: transform 0.6s cubic-bezier(0.25, 0.8, 0.25, 1);
233 | }
234 | }
235 |
236 | .md-expansion-panel-icon {
237 | transform: rotate(90deg);
238 | &:first-child {
239 | margin-right: 18px;
240 | }
241 | }
242 |
243 |
244 | &.md-open {
245 | > md-expansion-panel-expanded > md-expansion-panel-header .md-expansion-panel-header-container .md-expansion-panel-icon {
246 | transform: rotate(-90deg);
247 | }
248 |
249 | > md-expansion-panel.md-open > md-expansion-panel-collapsed .md-expansion-panel-icon {
250 | transform: rotate(-90deg);
251 | }
252 | }
253 | }
254 |
255 |
256 |
257 | @keyframes panelBodyHeaderStickyHoverIn {
258 | 0% {
259 | box-shadow: 0 0 0 0 transparent;
260 | }
261 | 100% {
262 | box-shadow: 0px 2px 4px 0 rgba(0, 0, 0, 0.16);
263 | }
264 | }
265 |
266 | @keyframes panelBodyHeaderStickyHoverOut {
267 | 0% {
268 | box-shadow: 0px 2px 4px 0 rgba(0, 0, 0, 0.16);
269 | }
270 | 100% {
271 | box-shadow: 0 0 0 0 transparent;
272 | }
273 | }
274 |
--------------------------------------------------------------------------------
/dist/md-expansion-panel.min.css:
--------------------------------------------------------------------------------
1 | md-expansion-panel,md-expansion-panel .md-expansion-panel-footer-container,md-expansion-panel .md-expansion-panel-header-container,md-expansion-panel md-expansion-panel-collapsed{background:#fff}md-expansion-panel .md-expansion-panel-footer-container .md-summary,md-expansion-panel .md-expansion-panel-footer-container .md-title,md-expansion-panel .md-expansion-panel-header-container .md-summary,md-expansion-panel .md-expansion-panel-header-container .md-title,md-expansion-panel md-expansion-panel-collapsed .md-summary,md-expansion-panel md-expansion-panel-collapsed .md-title{color:#333}md-expansion-panel md-expansion-panel-footer .md-expansion-panel-footer-container,md-expansion-panel md-expansion-panel-header .md-expansion-panel-header-container{border-color:#ddd}md-expansion-panel .md-expansion-panel-icon svg{fill:#999}md-expansion-panel[disabled] md-expansion-panel-collapsed .md-summary,md-expansion-panel[disabled] md-expansion-panel-collapsed .md-title{color:#ddd}md-expansion-panel[disabled] .md-expansion-panel-icon svg{fill:#ddd}md-expansion-panel:not(.md-open):not([disabled]):focus,md-expansion-panel:not(.md-open):not([disabled]):focus md-expansion-panel-collapsed{background:#eee}.layout-padding>md-expansion-panel-group{padding:0}md-expansion-panel{display:block;position:relative;outline:none;margin-top:0;margin-bottom:0;padding:0;box-shadow:0 -1px 0 #e5e5e5,0 0 2px rgba(0,0,0,.12),0 2px 4px rgba(0,0,0,.24)}md-expansion-panel.md-open{margin-top:16px;margin-bottom:16px}md-expansion-panel.md-open:first-of-type{margin-top:0}md-expansion-panel.md-close{overflow:hidden}md-expansion-panel:not(.md-no-animation).md-open{-webkit-transition:margin-top .12s cubic-bezier(.25,.8,.25,1),margin-bottom .12s cubic-bezier(.25,.8,.25,1);transition:margin-top .12s cubic-bezier(.25,.8,.25,1),margin-bottom .12s cubic-bezier(.25,.8,.25,1)}md-expansion-panel:not(.md-no-animation).md-close{-webkit-transition:margin-top .08s cubic-bezier(.25,.8,.25,1),margin-bottom .08s cubic-bezier(.25,.8,.25,1);transition:margin-top .08s cubic-bezier(.25,.8,.25,1),margin-bottom .08s cubic-bezier(.25,.8,.25,1)}md-expansion-panel-collapsed .md-title,md-expansion-panel-header .md-title{-webkit-box-flex:1;-ms-flex:1;flex:1;font-size:16px;font-weight:600;min-width:80px;max-width:184px;overflow:hidden;text-overflow:ellipsis;text-align:left;white-space:nowrap}md-expansion-panel-collapsed .md-summary,md-expansion-panel-header .md-summary{-webkit-box-flex:1;-ms-flex:1;flex:1;font-size:13px;overflow:hidden;text-overflow:ellipsis;text-align:left;white-space:nowrap}md-expansion-panel md-expansion-panel-collapsed{display:-webkit-box;display:-ms-flexbox;display:flex;min-height:48px;line-height:48px;padding:0 24px;opacity:1;z-index:2;box-sizing:border-box}md-expansion-panel md-expansion-panel-collapsed.md-absolute{position:absolute}md-expansion-panel md-expansion-panel-collapsed.md-hide{opacity:0}md-expansion-panel:not(.md-no-animation) md-expansion-panel-collapsed.md-show{-webkit-transition:opacity .03s linear;transition:opacity .03s linear}md-expansion-panel:not(.md-no-animation) md-expansion-panel-collapsed.md-hide{-webkit-transition:opacity .1s cubic-bezier(.25,.8,.25,1);transition:opacity .1s cubic-bezier(.25,.8,.25,1)}md-expansion-panel md-expansion-panel-expanded{display:none;min-height:48px}md-expansion-panel md-expansion-panel-expanded.md-hide,md-expansion-panel md-expansion-panel-expanded.md-show{display:block}md-expansion-panel md-expansion-panel-expanded.md-scroll-y{overflow-y:auto}md-expansion-panel md-expansion-panel-expanded.md-overflow{overflow:hidden}md-expansion-panel md-expansion-panel-expanded md-expansion-panel-content{display:block;padding:16px 24px}md-expansion-panel:not(.md-no-animation) md-expansion-panel-expanded.md-show{-webkit-transition:max-height .12s cubic-bezier(.25,.8,.25,1),opacity .12s cubic-bezier(.25,.8,.25,1);transition:max-height .12s cubic-bezier(.25,.8,.25,1),opacity .12s cubic-bezier(.25,.8,.25,1)}md-expansion-panel:not(.md-no-animation) md-expansion-panel-expanded.md-hide{-webkit-transition:max-height .06s cubic-bezier(.25,.8,.25,1),opacity .06s cubic-bezier(.25,.8,.25,1);transition:max-height .06s cubic-bezier(.25,.8,.25,1),opacity .06s cubic-bezier(.25,.8,.25,1)}md-expansion-panel-header{display:block;position:relative;outline:none}md-expansion-panel-header .md-expansion-panel-header-container{display:-webkit-box;display:-ms-flexbox;display:flex;min-height:48px;line-height:48px;padding:0 24px;box-sizing:border-box;border-bottom:1px solid;-webkit-box-align:center;-ms-flex-align:center;align-items:center}md-expansion-panel-header.md-stick .md-expansion-panel-header-container{position:fixed;z-index:2;-webkit-animation:a .3s ease-out both;animation:a .3s ease-out both}md-expansion-panel-header.md-no-stick .md-expansion-panel-header-container{-webkit-animation:b .3s ease-out both;animation:b .3s ease-out both}md-expansion-panel-footer{display:block;position:relative}md-expansion-panel-footer.md-hide,md-expansion-panel-footer.md-show{display:block}md-expansion-panel-footer .md-expansion-panel-footer-container{display:-webkit-box;display:-ms-flexbox;display:flex;min-height:48px;line-height:48px;padding:0 24px;border-top:1px solid;box-sizing:border-box}md-expansion-panel-footer.md-stick .md-expansion-panel-footer-container{position:fixed;z-index:2}md-expansion-panel:not(.md-no-animation) .md-expansion-panel-icon{-webkit-transition:-webkit-transform .6s cubic-bezier(.25,.8,.25,1);transition:-webkit-transform .6s cubic-bezier(.25,.8,.25,1);transition:transform .6s cubic-bezier(.25,.8,.25,1);transition:transform .6s cubic-bezier(.25,.8,.25,1),-webkit-transform .6s cubic-bezier(.25,.8,.25,1)}md-expansion-panel .md-expansion-panel-icon{-webkit-transform:rotate(90deg);transform:rotate(90deg)}md-expansion-panel .md-expansion-panel-icon:first-child{margin-right:18px}md-expansion-panel.md-open>md-expansion-panel-expanded>md-expansion-panel-header .md-expansion-panel-header-container .md-expansion-panel-icon,md-expansion-panel.md-open>md-expansion-panel.md-open>md-expansion-panel-collapsed .md-expansion-panel-icon{-webkit-transform:rotate(-90deg);transform:rotate(-90deg)}@-webkit-keyframes a{0%{box-shadow:0 0 0 0 transparent}to{box-shadow:0 2px 4px 0 rgba(0,0,0,.16)}}@keyframes a{0%{box-shadow:0 0 0 0 transparent}to{box-shadow:0 2px 4px 0 rgba(0,0,0,.16)}}@-webkit-keyframes b{0%{box-shadow:0 2px 4px 0 rgba(0,0,0,.16)}to{box-shadow:0 0 0 0 transparent}}@keyframes b{0%{box-shadow:0 2px 4px 0 rgba(0,0,0,.16)}to{box-shadow:0 0 0 0 transparent}}
--------------------------------------------------------------------------------
/src/js/expansionPanelGroup.service.js:
--------------------------------------------------------------------------------
1 | angular
2 | .module('material.components.expansionPanels')
3 | .factory('$mdExpansionPanelGroup', expansionPanelGroupService);
4 |
5 |
6 | /**
7 | * @ngdoc service
8 | * @name $mdExpansionPanelGroup
9 | * @module material.components.expansionPanels
10 | *
11 | * @description
12 | * Expand and collapse Expansion Panel using its `md-component-id`
13 | *
14 | * @example
15 | * $mdExpansionPanelGroup('comonentId').then(function (instance) {
16 | * instance.register({
17 | * componentId: 'cardComponentId',
18 | * templateUrl: 'template.html',
19 | * controller: 'Controller'
20 | * });
21 | * instance.add('cardComponentId', {local: localData});
22 | * instance.remove('cardComponentId', {animation: false});
23 | * instance.removeAll({animation: false});
24 | * });
25 | */
26 | expansionPanelGroupService.$inject = ['$mdComponentRegistry', '$mdUtil', '$mdExpansionPanel', '$templateRequest', '$rootScope', '$compile', '$controller', '$q', '$log'];
27 | function expansionPanelGroupService($mdComponentRegistry, $mdUtil, $mdExpansionPanel, $templateRequest, $rootScope, $compile, $controller, $q, $log) {
28 | var errorMsg = "ExpansionPanelGroup '{0}' is not available! Did you use md-component-id='{0}'?";
29 | var service = {
30 | find: findInstance,
31 | waitFor: waitForInstance
32 | };
33 |
34 | return function (handle) {
35 | if (handle === undefined) { return service; }
36 | return findInstance(handle);
37 | };
38 |
39 |
40 |
41 | function findInstance(handle) {
42 | var instance = $mdComponentRegistry.get(handle);
43 |
44 | if (!instance) {
45 | // Report missing instance
46 | $log.error( $mdUtil.supplant(errorMsg, [handle || ""]) );
47 | return undefined;
48 | }
49 |
50 | return createGroupInstance(instance);
51 | }
52 |
53 | function waitForInstance(handle) {
54 | var deffered = $q.defer();
55 |
56 | $mdComponentRegistry.when(handle).then(function (instance) {
57 | deffered.resolve(createGroupInstance(instance));
58 | }).catch(function (error) {
59 | deffered.reject();
60 | $log.error(error);
61 | });
62 |
63 | return deffered.promise;
64 | }
65 |
66 |
67 |
68 |
69 |
70 | // --- returned service for group instance ---
71 |
72 | function createGroupInstance(instance) {
73 | var service = {
74 | add: add,
75 | register: register,
76 | getAll: getAll,
77 | getOpen: getOpen,
78 | remove: remove,
79 | removeAll: removeAll,
80 | collapseAll: collapseAll,
81 | onChange: onChange,
82 | count: count
83 | };
84 |
85 | return service;
86 |
87 |
88 | function register(name, options) {
89 | if (typeof name !== 'string') {
90 | throw Error('$mdExpansionPanelGroup.register() Expects name to be a string');
91 | }
92 |
93 | validateOptions(options);
94 | instance.register(name, options);
95 | }
96 |
97 | function remove(componentId, options) {
98 | return instance.remove(componentId, options);
99 | }
100 |
101 | function removeAll(options) {
102 | instance.removeAll(options);
103 | }
104 |
105 | function onChange(callback) {
106 | return instance.onChange(callback);
107 | }
108 |
109 | function count() {
110 | return instance.count();
111 | }
112 |
113 | function getAll() {
114 | return instance.getAll();
115 | }
116 |
117 | function getOpen() {
118 | return instance.getOpen();
119 | }
120 |
121 | function collapseAll(noAnimation) {
122 | instance.collapseAll(noAnimation);
123 | }
124 |
125 |
126 | function add(options, locals) {
127 | locals = locals || {};
128 | // assume if options is a string then they are calling a registered card by its component id
129 | if (typeof options === 'string') {
130 | // call add panel with the stored options
131 | return add(instance.getRegistered(options), locals);
132 | }
133 |
134 | validateOptions(options);
135 | if (options.componentId && instance.isPanelActive(options.componentId)) {
136 | return $q.reject('panel with componentId "' + options.componentId + '" is currently active');
137 | }
138 |
139 |
140 | var deffered = $q.defer();
141 | var scope = $rootScope.$new();
142 | angular.extend(scope, options.scope);
143 |
144 | getTemplate(options, function (template) {
145 | var element = angular.element(template);
146 | var componentId = options.componentId || element.attr('md-component-id') || '_panelComponentId_' + $mdUtil.nextUid();
147 | var panelPromise = $mdExpansionPanel().waitFor(componentId);
148 | element.attr('md-component-id', componentId);
149 |
150 | var linkFunc = $compile(element);
151 | if (options.controller) {
152 | angular.extend(locals, options.locals || {});
153 | locals.$scope = scope;
154 | locals.$panel = panelPromise;
155 | var invokeCtrl = $controller(options.controller, locals, true);
156 | var ctrl = invokeCtrl();
157 | element.data('$ngControllerController', ctrl);
158 | element.children().data('$ngControllerController', ctrl);
159 | if (options.controllerAs) {
160 | scope[options.controllerAs] = ctrl;
161 | }
162 | }
163 |
164 | // link after the element is added so we can find card manager directive
165 | instance.$element.append(element);
166 | linkFunc(scope);
167 |
168 | panelPromise.then(function (instance) {
169 | deffered.resolve(instance);
170 | });
171 | });
172 |
173 | return deffered.promise;
174 | }
175 |
176 |
177 | function validateOptions(options) {
178 | if (typeof options !== 'object' || options === null) {
179 | throw Error('$mdExapnsionPanelGroup.add()/.register() : Requires an options object to be passed in');
180 | }
181 |
182 | // if none of these exist then a dialog box cannot be created
183 | if (!options.template && !options.templateUrl) {
184 | throw Error('$mdExapnsionPanelGroup.add()/.register() : Is missing required paramters to create. Required One of the following: template, templateUrl');
185 | }
186 | }
187 |
188 |
189 |
190 | function getTemplate(options, callback) {
191 | var template;
192 |
193 | if (options.templateUrl !== undefined) {
194 | $templateRequest(options.templateUrl)
195 | .then(function(response) {
196 | callback(response);
197 | });
198 | } else {
199 | callback(options.template);
200 | }
201 | }
202 | }
203 | }
204 |
--------------------------------------------------------------------------------
/docs/js/expansionPanelGroup.service.js:
--------------------------------------------------------------------------------
1 | (function(){"use strict";angular
2 | .module('material.components.expansionPanels')
3 | .factory('$mdExpansionPanelGroup', expansionPanelGroupService);
4 |
5 |
6 | /**
7 | * @ngdoc service
8 | * @name $mdExpansionPanelGroup
9 | * @module material.components.expansionPanels
10 | *
11 | * @description
12 | * Expand and collapse Expansion Panel using its `md-component-id`
13 | *
14 | * @example
15 | * $mdExpansionPanelGroup('comonentId').then(function (instance) {
16 | * instance.register({
17 | * componentId: 'cardComponentId',
18 | * templateUrl: 'template.html',
19 | * controller: 'Controller'
20 | * });
21 | * instance.add('cardComponentId', {local: localData});
22 | * instance.remove('cardComponentId', {animation: false});
23 | * instance.removeAll({animation: false});
24 | * });
25 | */
26 | expansionPanelGroupService.$inject = ['$mdComponentRegistry', '$mdUtil', '$mdExpansionPanel', '$templateRequest', '$rootScope', '$compile', '$controller', '$q', '$log'];
27 | function expansionPanelGroupService($mdComponentRegistry, $mdUtil, $mdExpansionPanel, $templateRequest, $rootScope, $compile, $controller, $q, $log) {
28 | var errorMsg = "ExpansionPanelGroup '{0}' is not available! Did you use md-component-id='{0}'?";
29 | var service = {
30 | find: findInstance,
31 | waitFor: waitForInstance
32 | };
33 |
34 | return function (handle) {
35 | if (handle === undefined) { return service; }
36 | return findInstance(handle);
37 | };
38 |
39 |
40 |
41 | function findInstance(handle) {
42 | var instance = $mdComponentRegistry.get(handle);
43 |
44 | if (!instance) {
45 | // Report missing instance
46 | $log.error( $mdUtil.supplant(errorMsg, [handle || ""]) );
47 | return undefined;
48 | }
49 |
50 | return createGroupInstance(instance);
51 | }
52 |
53 | function waitForInstance(handle) {
54 | var deffered = $q.defer();
55 |
56 | $mdComponentRegistry.when(handle).then(function (instance) {
57 | deffered.resolve(createGroupInstance(instance));
58 | }).catch(function (error) {
59 | deffered.reject();
60 | $log.error(error);
61 | });
62 |
63 | return deffered.promise;
64 | }
65 |
66 |
67 |
68 |
69 |
70 | // --- returned service for group instance ---
71 |
72 | function createGroupInstance(instance) {
73 | var service = {
74 | add: add,
75 | register: register,
76 | getAll: getAll,
77 | getOpen: getOpen,
78 | remove: remove,
79 | removeAll: removeAll,
80 | collapseAll: collapseAll,
81 | onChange: onChange,
82 | count: count
83 | };
84 |
85 | return service;
86 |
87 |
88 | function register(name, options) {
89 | if (typeof name !== 'string') {
90 | throw Error('$mdExpansionPanelGroup.register() Expects name to be a string');
91 | }
92 |
93 | validateOptions(options);
94 | instance.register(name, options);
95 | }
96 |
97 | function remove(componentId, options) {
98 | return instance.remove(componentId, options);
99 | }
100 |
101 | function removeAll(options) {
102 | instance.removeAll(options);
103 | }
104 |
105 | function onChange(callback) {
106 | return instance.onChange(callback);
107 | }
108 |
109 | function count() {
110 | return instance.count();
111 | }
112 |
113 | function getAll() {
114 | return instance.getAll();
115 | }
116 |
117 | function getOpen() {
118 | return instance.getOpen();
119 | }
120 |
121 | function collapseAll(noAnimation) {
122 | instance.collapseAll(noAnimation);
123 | }
124 |
125 |
126 | function add(options, locals) {
127 | locals = locals || {};
128 | // assume if options is a string then they are calling a registered card by its component id
129 | if (typeof options === 'string') {
130 | // call add panel with the stored options
131 | return add(instance.getRegistered(options), locals);
132 | }
133 |
134 | validateOptions(options);
135 | if (options.componentId && instance.isPanelActive(options.componentId)) {
136 | return $q.reject('panel with componentId "' + options.componentId + '" is currently active');
137 | }
138 |
139 |
140 | var deffered = $q.defer();
141 | var scope = $rootScope.$new();
142 | angular.extend(scope, options.scope);
143 |
144 | getTemplate(options, function (template) {
145 | var element = angular.element(template);
146 | var componentId = options.componentId || element.attr('md-component-id') || '_panelComponentId_' + $mdUtil.nextUid();
147 | var panelPromise = $mdExpansionPanel().waitFor(componentId);
148 | element.attr('md-component-id', componentId);
149 |
150 | var linkFunc = $compile(element);
151 | if (options.controller) {
152 | angular.extend(locals, options.locals || {});
153 | locals.$scope = scope;
154 | locals.$panel = panelPromise;
155 | var invokeCtrl = $controller(options.controller, locals, true);
156 | var ctrl = invokeCtrl();
157 | element.data('$ngControllerController', ctrl);
158 | element.children().data('$ngControllerController', ctrl);
159 | if (options.controllerAs) {
160 | scope[options.controllerAs] = ctrl;
161 | }
162 | }
163 |
164 | // link after the element is added so we can find card manager directive
165 | instance.$element.append(element);
166 | linkFunc(scope);
167 |
168 | panelPromise.then(function (instance) {
169 | deffered.resolve(instance);
170 | });
171 | });
172 |
173 | return deffered.promise;
174 | }
175 |
176 |
177 | function validateOptions(options) {
178 | if (typeof options !== 'object' || options === null) {
179 | throw Error('$mdExapnsionPanelGroup.add()/.register() : Requires an options object to be passed in');
180 | }
181 |
182 | // if none of these exist then a dialog box cannot be created
183 | if (!options.template && !options.templateUrl) {
184 | throw Error('$mdExapnsionPanelGroup.add()/.register() : Is missing required paramters to create. Required One of the following: template, templateUrl');
185 | }
186 | }
187 |
188 |
189 |
190 | function getTemplate(options, callback) {
191 | var template;
192 |
193 | if (options.templateUrl !== undefined) {
194 | $templateRequest(options.templateUrl)
195 | .then(function(response) {
196 | callback(response);
197 | });
198 | } else {
199 | callback(options.template);
200 | }
201 | }
202 | }
203 | }
204 | }());
--------------------------------------------------------------------------------
/docs/expansionPanels.css:
--------------------------------------------------------------------------------
1 | .layout-padding > md-expansion-panel-group {
2 | padding: 0; }
3 |
4 | /* --- Expansion Panel --- */
5 | md-expansion-panel {
6 | display: block;
7 | position: relative;
8 | outline: none;
9 | margin-top: 0;
10 | margin-bottom: 0;
11 | padding: 0;
12 | box-shadow: 0 -1px 0 #e5e5e5, 0 0 2px rgba(0, 0, 0, 0.12), 0 2px 4px rgba(0, 0, 0, 0.24); }
13 | md-expansion-panel.md-open {
14 | margin-top: 16px;
15 | margin-bottom: 16px; }
16 | md-expansion-panel.md-open:first-of-type {
17 | margin-top: 0; }
18 | md-expansion-panel.md-close {
19 | overflow: hidden; }
20 | md-expansion-panel:not(.md-no-animation).md-open {
21 | -webkit-transition: margin-top 0.12s cubic-bezier(0.25, 0.8, 0.25, 1), margin-bottom 0.12s cubic-bezier(0.25, 0.8, 0.25, 1);
22 | transition: margin-top 0.12s cubic-bezier(0.25, 0.8, 0.25, 1), margin-bottom 0.12s cubic-bezier(0.25, 0.8, 0.25, 1); }
23 | md-expansion-panel:not(.md-no-animation).md-close {
24 | -webkit-transition: margin-top 0.08s cubic-bezier(0.25, 0.8, 0.25, 1), margin-bottom 0.08s cubic-bezier(0.25, 0.8, 0.25, 1);
25 | transition: margin-top 0.08s cubic-bezier(0.25, 0.8, 0.25, 1), margin-bottom 0.08s cubic-bezier(0.25, 0.8, 0.25, 1); }
26 |
27 | md-expansion-panel-collapsed .md-title,
28 | md-expansion-panel-header .md-title {
29 | -webkit-box-flex: 1;
30 | -ms-flex: 1;
31 | flex: 1;
32 | font-size: 16px;
33 | font-weight: 600;
34 | min-width: 80px;
35 | max-width: 184px;
36 | overflow: hidden;
37 | text-overflow: ellipsis;
38 | text-align: left;
39 | white-space: nowrap; }
40 |
41 | md-expansion-panel-collapsed .md-summary,
42 | md-expansion-panel-header .md-summary {
43 | -webkit-box-flex: 1;
44 | -ms-flex: 1;
45 | flex: 1;
46 | font-size: 13px;
47 | overflow: hidden;
48 | text-overflow: ellipsis;
49 | text-align: left;
50 | white-space: nowrap; }
51 |
52 | /* --- Expansion Panel Collapsed ---- */
53 | md-expansion-panel md-expansion-panel-collapsed {
54 | display: -webkit-box;
55 | display: -ms-flexbox;
56 | display: flex;
57 | min-height: 48px;
58 | line-height: 48px;
59 | padding: 0 24px;
60 | opacity: 1;
61 | z-index: 2;
62 | box-sizing: border-box; }
63 | md-expansion-panel md-expansion-panel-collapsed.md-absolute {
64 | position: absolute; }
65 | md-expansion-panel md-expansion-panel-collapsed.md-hide {
66 | opacity: 0; }
67 |
68 | md-expansion-panel:not(.md-no-animation) md-expansion-panel-collapsed.md-show {
69 | -webkit-transition: opacity 0.03s linear;
70 | transition: opacity 0.03s linear; }
71 |
72 | md-expansion-panel:not(.md-no-animation) md-expansion-panel-collapsed.md-hide {
73 | -webkit-transition: opacity 0.1s cubic-bezier(0.25, 0.8, 0.25, 1);
74 | transition: opacity 0.1s cubic-bezier(0.25, 0.8, 0.25, 1); }
75 |
76 | /* --- Expansion Panel Expanded --- */
77 | md-expansion-panel md-expansion-panel-expanded {
78 | display: none;
79 | min-height: 48px; }
80 | md-expansion-panel md-expansion-panel-expanded.md-show, md-expansion-panel md-expansion-panel-expanded.md-hide {
81 | display: block; }
82 | md-expansion-panel md-expansion-panel-expanded.md-scroll-y {
83 | overflow-y: auto; }
84 | md-expansion-panel md-expansion-panel-expanded.md-overflow {
85 | overflow: hidden; }
86 | md-expansion-panel md-expansion-panel-expanded md-expansion-panel-content {
87 | display: block;
88 | padding: 16px 24px; }
89 |
90 | md-expansion-panel:not(.md-no-animation) md-expansion-panel-expanded.md-show {
91 | -webkit-transition: max-height 0.12s cubic-bezier(0.25, 0.8, 0.25, 1), opacity 0.12s cubic-bezier(0.25, 0.8, 0.25, 1);
92 | transition: max-height 0.12s cubic-bezier(0.25, 0.8, 0.25, 1), opacity 0.12s cubic-bezier(0.25, 0.8, 0.25, 1); }
93 |
94 | md-expansion-panel:not(.md-no-animation) md-expansion-panel-expanded.md-hide {
95 | -webkit-transition: max-height 0.06s cubic-bezier(0.25, 0.8, 0.25, 1), opacity 0.06s cubic-bezier(0.25, 0.8, 0.25, 1);
96 | transition: max-height 0.06s cubic-bezier(0.25, 0.8, 0.25, 1), opacity 0.06s cubic-bezier(0.25, 0.8, 0.25, 1); }
97 |
98 | /* --- Expansion Panel Header --- */
99 | md-expansion-panel-header {
100 | display: block;
101 | position: relative;
102 | outline: none; }
103 | md-expansion-panel-header .md-expansion-panel-header-container {
104 | display: -webkit-box;
105 | display: -ms-flexbox;
106 | display: flex;
107 | min-height: 48px;
108 | line-height: 48px;
109 | padding: 0 24px;
110 | box-sizing: border-box;
111 | border-bottom: 1px solid;
112 | -webkit-box-align: center;
113 | -ms-flex-align: center;
114 | align-items: center; }
115 | md-expansion-panel-header.md-stick .md-expansion-panel-header-container {
116 | position: fixed;
117 | z-index: 2;
118 | -webkit-animation: panelBodyHeaderStickyHoverIn 0.3s ease-out both;
119 | animation: panelBodyHeaderStickyHoverIn 0.3s ease-out both; }
120 | md-expansion-panel-header.md-no-stick .md-expansion-panel-header-container {
121 | -webkit-animation: panelBodyHeaderStickyHoverOut 0.3s ease-out both;
122 | animation: panelBodyHeaderStickyHoverOut 0.3s ease-out both; }
123 |
124 | /* --- Expansion Panel Footer --- */
125 | md-expansion-panel-footer {
126 | display: block;
127 | position: relative; }
128 | md-expansion-panel-footer.md-show, md-expansion-panel-footer.md-hide {
129 | display: block; }
130 | md-expansion-panel-footer .md-expansion-panel-footer-container {
131 | display: -webkit-box;
132 | display: -ms-flexbox;
133 | display: flex;
134 | min-height: 48px;
135 | line-height: 48px;
136 | padding: 0 24px;
137 | border-top: 1px solid;
138 | box-sizing: border-box; }
139 | md-expansion-panel-footer.md-stick .md-expansion-panel-footer-container {
140 | position: fixed;
141 | z-index: 2; }
142 |
143 | /* --- expand icon --- */
144 | md-expansion-panel:not(.md-no-animation) .md-expansion-panel-icon {
145 | -webkit-transition: -webkit-transform 0.6s cubic-bezier(0.25, 0.8, 0.25, 1);
146 | transition: -webkit-transform 0.6s cubic-bezier(0.25, 0.8, 0.25, 1);
147 | transition: transform 0.6s cubic-bezier(0.25, 0.8, 0.25, 1);
148 | transition: transform 0.6s cubic-bezier(0.25, 0.8, 0.25, 1), -webkit-transform 0.6s cubic-bezier(0.25, 0.8, 0.25, 1); }
149 |
150 | md-expansion-panel .md-expansion-panel-icon {
151 | -webkit-transform: rotate(90deg);
152 | transform: rotate(90deg); }
153 | md-expansion-panel .md-expansion-panel-icon:first-child {
154 | margin-right: 18px; }
155 |
156 | md-expansion-panel.md-open > md-expansion-panel-expanded > md-expansion-panel-header .md-expansion-panel-header-container .md-expansion-panel-icon {
157 | -webkit-transform: rotate(-90deg);
158 | transform: rotate(-90deg); }
159 |
160 | md-expansion-panel.md-open > md-expansion-panel.md-open > md-expansion-panel-collapsed .md-expansion-panel-icon {
161 | -webkit-transform: rotate(-90deg);
162 | transform: rotate(-90deg); }
163 |
164 | @-webkit-keyframes panelBodyHeaderStickyHoverIn {
165 | 0% {
166 | box-shadow: 0 0 0 0 transparent; }
167 | 100% {
168 | box-shadow: 0px 2px 4px 0 rgba(0, 0, 0, 0.16); } }
169 |
170 | @keyframes panelBodyHeaderStickyHoverIn {
171 | 0% {
172 | box-shadow: 0 0 0 0 transparent; }
173 | 100% {
174 | box-shadow: 0px 2px 4px 0 rgba(0, 0, 0, 0.16); } }
175 |
176 | @-webkit-keyframes panelBodyHeaderStickyHoverOut {
177 | 0% {
178 | box-shadow: 0px 2px 4px 0 rgba(0, 0, 0, 0.16); }
179 | 100% {
180 | box-shadow: 0 0 0 0 transparent; } }
181 |
182 | @keyframes panelBodyHeaderStickyHoverOut {
183 | 0% {
184 | box-shadow: 0px 2px 4px 0 rgba(0, 0, 0, 0.16); }
185 | 100% {
186 | box-shadow: 0 0 0 0 transparent; } }
187 |
--------------------------------------------------------------------------------
/dist/md-expansion-panel.css:
--------------------------------------------------------------------------------
1 | md-expansion-panel {
2 | background: #FFF; }
3 | md-expansion-panel md-expansion-panel-collapsed,
4 | md-expansion-panel .md-expansion-panel-footer-container,
5 | md-expansion-panel .md-expansion-panel-header-container {
6 | background: #FFF; }
7 | md-expansion-panel md-expansion-panel-collapsed .md-title,
8 | md-expansion-panel md-expansion-panel-collapsed .md-summary,
9 | md-expansion-panel .md-expansion-panel-footer-container .md-title,
10 | md-expansion-panel .md-expansion-panel-footer-container .md-summary,
11 | md-expansion-panel .md-expansion-panel-header-container .md-title,
12 | md-expansion-panel .md-expansion-panel-header-container .md-summary {
13 | color: #333; }
14 | md-expansion-panel md-expansion-panel-footer .md-expansion-panel-footer-container,
15 | md-expansion-panel md-expansion-panel-header .md-expansion-panel-header-container {
16 | border-color: #DDD; }
17 | md-expansion-panel .md-expansion-panel-icon svg {
18 | fill: #999; }
19 | md-expansion-panel[disabled] md-expansion-panel-collapsed .md-title,
20 | md-expansion-panel[disabled] md-expansion-panel-collapsed .md-summary {
21 | color: #DDD; }
22 | md-expansion-panel[disabled] .md-expansion-panel-icon svg {
23 | fill: #DDD; }
24 | md-expansion-panel:not(.md-open):not([disabled]):focus,
25 | md-expansion-panel:not(.md-open):not([disabled]):focus md-expansion-panel-collapsed {
26 | background: #EEE; }
27 |
28 | .layout-padding > md-expansion-panel-group {
29 | padding: 0; }
30 |
31 | /* --- Expansion Panel --- */
32 | md-expansion-panel {
33 | display: block;
34 | position: relative;
35 | outline: none;
36 | margin-top: 0;
37 | margin-bottom: 0;
38 | padding: 0;
39 | box-shadow: 0 -1px 0 #e5e5e5, 0 0 2px rgba(0, 0, 0, 0.12), 0 2px 4px rgba(0, 0, 0, 0.24); }
40 | md-expansion-panel.md-open {
41 | margin-top: 16px;
42 | margin-bottom: 16px; }
43 | md-expansion-panel.md-open:first-of-type {
44 | margin-top: 0; }
45 | md-expansion-panel.md-close {
46 | overflow: hidden; }
47 | md-expansion-panel:not(.md-no-animation).md-open {
48 | -webkit-transition: margin-top 0.12s cubic-bezier(0.25, 0.8, 0.25, 1), margin-bottom 0.12s cubic-bezier(0.25, 0.8, 0.25, 1);
49 | transition: margin-top 0.12s cubic-bezier(0.25, 0.8, 0.25, 1), margin-bottom 0.12s cubic-bezier(0.25, 0.8, 0.25, 1); }
50 | md-expansion-panel:not(.md-no-animation).md-close {
51 | -webkit-transition: margin-top 0.08s cubic-bezier(0.25, 0.8, 0.25, 1), margin-bottom 0.08s cubic-bezier(0.25, 0.8, 0.25, 1);
52 | transition: margin-top 0.08s cubic-bezier(0.25, 0.8, 0.25, 1), margin-bottom 0.08s cubic-bezier(0.25, 0.8, 0.25, 1); }
53 |
54 | md-expansion-panel-collapsed .md-title,
55 | md-expansion-panel-header .md-title {
56 | -webkit-box-flex: 1;
57 | -ms-flex: 1;
58 | flex: 1;
59 | font-size: 16px;
60 | font-weight: 600;
61 | min-width: 80px;
62 | max-width: 184px;
63 | overflow: hidden;
64 | text-overflow: ellipsis;
65 | text-align: left;
66 | white-space: nowrap; }
67 |
68 | md-expansion-panel-collapsed .md-summary,
69 | md-expansion-panel-header .md-summary {
70 | -webkit-box-flex: 1;
71 | -ms-flex: 1;
72 | flex: 1;
73 | font-size: 13px;
74 | overflow: hidden;
75 | text-overflow: ellipsis;
76 | text-align: left;
77 | white-space: nowrap; }
78 |
79 | /* --- Expansion Panel Collapsed ---- */
80 | md-expansion-panel md-expansion-panel-collapsed {
81 | display: -webkit-box;
82 | display: -ms-flexbox;
83 | display: flex;
84 | min-height: 48px;
85 | line-height: 48px;
86 | padding: 0 24px;
87 | opacity: 1;
88 | z-index: 2;
89 | box-sizing: border-box; }
90 | md-expansion-panel md-expansion-panel-collapsed.md-absolute {
91 | position: absolute; }
92 | md-expansion-panel md-expansion-panel-collapsed.md-hide {
93 | opacity: 0; }
94 |
95 | md-expansion-panel:not(.md-no-animation) md-expansion-panel-collapsed.md-show {
96 | -webkit-transition: opacity 0.03s linear;
97 | transition: opacity 0.03s linear; }
98 |
99 | md-expansion-panel:not(.md-no-animation) md-expansion-panel-collapsed.md-hide {
100 | -webkit-transition: opacity 0.1s cubic-bezier(0.25, 0.8, 0.25, 1);
101 | transition: opacity 0.1s cubic-bezier(0.25, 0.8, 0.25, 1); }
102 |
103 | /* --- Expansion Panel Expanded --- */
104 | md-expansion-panel md-expansion-panel-expanded {
105 | display: none;
106 | min-height: 48px; }
107 | md-expansion-panel md-expansion-panel-expanded.md-show, md-expansion-panel md-expansion-panel-expanded.md-hide {
108 | display: block; }
109 | md-expansion-panel md-expansion-panel-expanded.md-scroll-y {
110 | overflow-y: auto; }
111 | md-expansion-panel md-expansion-panel-expanded.md-overflow {
112 | overflow: hidden; }
113 | md-expansion-panel md-expansion-panel-expanded md-expansion-panel-content {
114 | display: block;
115 | padding: 16px 24px; }
116 |
117 | md-expansion-panel:not(.md-no-animation) md-expansion-panel-expanded.md-show {
118 | -webkit-transition: max-height 0.12s cubic-bezier(0.25, 0.8, 0.25, 1), opacity 0.12s cubic-bezier(0.25, 0.8, 0.25, 1);
119 | transition: max-height 0.12s cubic-bezier(0.25, 0.8, 0.25, 1), opacity 0.12s cubic-bezier(0.25, 0.8, 0.25, 1); }
120 |
121 | md-expansion-panel:not(.md-no-animation) md-expansion-panel-expanded.md-hide {
122 | -webkit-transition: max-height 0.06s cubic-bezier(0.25, 0.8, 0.25, 1), opacity 0.06s cubic-bezier(0.25, 0.8, 0.25, 1);
123 | transition: max-height 0.06s cubic-bezier(0.25, 0.8, 0.25, 1), opacity 0.06s cubic-bezier(0.25, 0.8, 0.25, 1); }
124 |
125 | /* --- Expansion Panel Header --- */
126 | md-expansion-panel-header {
127 | display: block;
128 | position: relative;
129 | outline: none; }
130 | md-expansion-panel-header .md-expansion-panel-header-container {
131 | display: -webkit-box;
132 | display: -ms-flexbox;
133 | display: flex;
134 | min-height: 48px;
135 | line-height: 48px;
136 | padding: 0 24px;
137 | box-sizing: border-box;
138 | border-bottom: 1px solid;
139 | -webkit-box-align: center;
140 | -ms-flex-align: center;
141 | align-items: center; }
142 | md-expansion-panel-header.md-stick .md-expansion-panel-header-container {
143 | position: fixed;
144 | z-index: 2;
145 | -webkit-animation: panelBodyHeaderStickyHoverIn 0.3s ease-out both;
146 | animation: panelBodyHeaderStickyHoverIn 0.3s ease-out both; }
147 | md-expansion-panel-header.md-no-stick .md-expansion-panel-header-container {
148 | -webkit-animation: panelBodyHeaderStickyHoverOut 0.3s ease-out both;
149 | animation: panelBodyHeaderStickyHoverOut 0.3s ease-out both; }
150 |
151 | /* --- Expansion Panel Footer --- */
152 | md-expansion-panel-footer {
153 | display: block;
154 | position: relative; }
155 | md-expansion-panel-footer.md-show, md-expansion-panel-footer.md-hide {
156 | display: block; }
157 | md-expansion-panel-footer .md-expansion-panel-footer-container {
158 | display: -webkit-box;
159 | display: -ms-flexbox;
160 | display: flex;
161 | min-height: 48px;
162 | line-height: 48px;
163 | padding: 0 24px;
164 | border-top: 1px solid;
165 | box-sizing: border-box; }
166 | md-expansion-panel-footer.md-stick .md-expansion-panel-footer-container {
167 | position: fixed;
168 | z-index: 2; }
169 |
170 | /* --- expand icon --- */
171 | md-expansion-panel:not(.md-no-animation) .md-expansion-panel-icon {
172 | -webkit-transition: -webkit-transform 0.6s cubic-bezier(0.25, 0.8, 0.25, 1);
173 | transition: -webkit-transform 0.6s cubic-bezier(0.25, 0.8, 0.25, 1);
174 | transition: transform 0.6s cubic-bezier(0.25, 0.8, 0.25, 1);
175 | transition: transform 0.6s cubic-bezier(0.25, 0.8, 0.25, 1), -webkit-transform 0.6s cubic-bezier(0.25, 0.8, 0.25, 1); }
176 |
177 | md-expansion-panel .md-expansion-panel-icon {
178 | -webkit-transform: rotate(90deg);
179 | transform: rotate(90deg); }
180 | md-expansion-panel .md-expansion-panel-icon:first-child {
181 | margin-right: 18px; }
182 |
183 | md-expansion-panel.md-open > md-expansion-panel-expanded > md-expansion-panel-header .md-expansion-panel-header-container .md-expansion-panel-icon {
184 | -webkit-transform: rotate(-90deg);
185 | transform: rotate(-90deg); }
186 |
187 | md-expansion-panel.md-open > md-expansion-panel.md-open > md-expansion-panel-collapsed .md-expansion-panel-icon {
188 | -webkit-transform: rotate(-90deg);
189 | transform: rotate(-90deg); }
190 |
191 | @-webkit-keyframes panelBodyHeaderStickyHoverIn {
192 | 0% {
193 | box-shadow: 0 0 0 0 transparent; }
194 | 100% {
195 | box-shadow: 0px 2px 4px 0 rgba(0, 0, 0, 0.16); } }
196 |
197 | @keyframes panelBodyHeaderStickyHoverIn {
198 | 0% {
199 | box-shadow: 0 0 0 0 transparent; }
200 | 100% {
201 | box-shadow: 0px 2px 4px 0 rgba(0, 0, 0, 0.16); } }
202 |
203 | @-webkit-keyframes panelBodyHeaderStickyHoverOut {
204 | 0% {
205 | box-shadow: 0px 2px 4px 0 rgba(0, 0, 0, 0.16); }
206 | 100% {
207 | box-shadow: 0 0 0 0 transparent; } }
208 |
209 | @keyframes panelBodyHeaderStickyHoverOut {
210 | 0% {
211 | box-shadow: 0px 2px 4px 0 rgba(0, 0, 0, 0.16); }
212 | 100% {
213 | box-shadow: 0 0 0 0 transparent; } }
214 |
--------------------------------------------------------------------------------
/dist/md-expansion-panel.min.js:
--------------------------------------------------------------------------------
1 | !function(){"use strict";angular.module("material.components.expansionPanels",["material.core"])}(),function(){"use strict";angular.module("material.components.expansionPanels").run(["$templateCache",function(n){n.put("icons/ic_keyboard_arrow_right_black_24px.svg",'\n \n \n ')}])}(),function(){"use strict";function n(){function n(n,e){var o="Invalid HTML for md-expansion-panel: ";if(n.attr("tabindex",e.tabindex||"0"),null===n[0].querySelector("md-expansion-panel-collapsed"))throw Error(o+"Expected a child element of `md-epxansion-panel-collapsed`");if(null===n[0].querySelector("md-expansion-panel-expanded"))throw Error(o+"Expected a child element of `md-epxansion-panel-expanded`");return function(n,e,o,t){var i=t[0],r=t[1];i.epxansionPanelGroupCtrl=r||void 0,i.init()}}function o(n,o,t,i,r,a,s,l,c,d,u,p){function m(n){var e=a.KEY_CODE;switch(n.keyCode){case e.ENTER:g();break;case e.ESCAPE:x()}}function f(){F=!0,M===!0&&v()}function v(){return F===!1?void(M=!0):("function"==typeof q&&(q(),q=void 0),D.componentId&&D.epxansionPanelGroupCtrl&&D.epxansionPanelGroupCtrl.removePanel(D.componentId),void 0===t.mdComponentId&&t.$set("mdComponentId","_expansion_panel_id_"+s.nextUid()),D.componentId=t.mdComponentId,q=l.register({expand:g,collapse:x,remove:C,onRemove:$,isOpen:h,addClickCatcher:S,removeClickCatcher:_,componentId:t.mdComponentId},t.mdComponentId),void(D.epxansionPanelGroupCtrl&&D.epxansionPanelGroupCtrl.addPanel(D.componentId,{expand:g,collapse:x,remove:C,onRemove:$,destroy:E,isOpen:h})))}function h(){return W}function g(n){if(W!==!0&&L!==!0){W=!0,n=n||{};var t=d.defer();return D.epxansionPanelGroupCtrl&&D.epxansionPanelGroupCtrl.expandPanel(D.componentId),o.removeClass("md-close"),o.addClass("md-open"),n.animation===!1?o.addClass("md-no-animation"):o.removeClass("md-no-animation"),w(),O.hide(n),G.show(n),j&&j.show(n),N&&N.show(n),c(function(){t.resolve()},n.animation===!1?0:e),t.promise}}function x(n){if(W!==!1){W=!1,n=n||{};var t=d.defer();return o.addClass("md-close"),o.removeClass("md-open"),n.animation===!1?o.addClass("md-no-animation"):o.removeClass("md-no-animation"),P(),O.show(n),G.hide(n),j&&j.hide(n),N&&N.hide(n),c(function(){t.resolve()},n.animation===!1?0:e),t.promise}}function C(t){t=t||{};var i=d.defer();return D.epxansionPanelGroupCtrl&&D.epxansionPanelGroupCtrl.removePanel(D.componentId),"function"==typeof q&&(q(),q=void 0),t.animation===!1||W===!1?(n.$destroy(),o.remove(),i.resolve(),y()):(x(),c(function(){n.$destroy(),o.remove(),i.resolve(),y()},e)),i.promise}function $(n){B=n}function y(){"function"==typeof B&&(B(),B=void 0)}function E(){n.$destroy()}function w(){(N&&N.noSticky!==!0||j&&j.noSticky!==!0)&&(H=n.$watch(function(){return o[0].offsetTop},K,!0),z=n.$watch(function(){return o[0].offsetWidth},Y,!0),A=s.getNearestContentElement(o),"MD-CONTENT"===A.nodeName?(U=k(A),angular.element(A).on("scroll",K)):U=void 0,G.setHeight===!0&&G.$element.on("scroll",K),angular.element(i).on("scroll",K).on("resize",K).on("resize",Y))}function P(){"function"==typeof H&&(H(),H=void 0),"function"==typeof z&&(z(),z=void 0),A&&"MD-CONTENT"===A.nodeName&&angular.element(A).off("scroll",K),G.setHeight===!0&&G.$element.off("scroll",K),angular.element(i).off("scroll",K).off("resize",K).off("resize",Y)}function k(n){for(var e=n.parentNode;e&&e!==document;){if(b(e,"transform"))return e;e=e.parentNode}}function b(n,e){var o=!1;if(n){var t=i.getComputedStyle(n);o=void 0!==t[e]&&"none"!==t[e]}return o}function I(n){var e,o,t;t=G.setHeight===!0?G.$element[0].getBoundingClientRect():A.getBoundingClientRect();var i=U?U.getBoundingClientRect().top:0;e=Math.max(t.top,0),o=e+t.height,N&&N.noSticky===!1&&N.onScroll(e,o,i),j&&j.noSticky===!1&&j.onScroll(e,o,i)}function R(){var n=o[0].offsetWidth;N&&N.noSticky===!1&&N.onResize(n),j&&j.noSticky===!1&&j.onResize(n)}function S(e){T=s.createBackdrop(n),T[0].tabIndex=-1,"function"==typeof e&&T.on("click",e),u.enter(T,o.parent(),null,{duration:0}),o.css("z-index",60)}function _(){T&&(T.remove(),T.off("click"),T=void 0,o.css("z-index",""))}var O,G,j,N,q,A,H,z,B,U,T,D=this,F=!1,M=!1,W=!1,L=!1,K=r.throttle(I),Y=r.throttle(R);D.registerCollapsed=function(n){O=n},D.registerExpanded=function(n){G=n},D.registerHeader=function(n){j=n},D.registerFooter=function(n){N=n},void 0===t.mdComponentId?(t.$set("mdComponentId","_expansion_panel_id_"+s.nextUid()),v()):t.$observe("mdComponentId",function(){v()}),D.$element=o,D.expand=g,D.collapse=x,D.remove=C,D.destroy=E,D.onRemove=$,D.init=f,void 0!==t.ngDisabled?n.$watch(t.ngDisabled,function(n){L=n,o.attr("tabindex",L?-1:0)}):void 0!==t.disabled&&(L=void 0!==t.disabled&&"false"!==t.disabled&&t.disabled!==!1,o.attr("tabindex",L?-1:0)),o.on("focus",function(n){o.on("keydown",m)}).on("blur",function(n){o.off("keydown",m)}),n.$panel={collapse:x,expand:g,remove:C,isOpen:h},n.$on("$destroy",function(){_(),"function"==typeof q&&(q(),q=void 0),P()})}var t={restrict:"E",require:["mdExpansionPanel","?^^mdExpansionPanelGroup"],scope:!0,compile:n,controller:["$scope","$element","$attrs","$window","$$rAF","$mdConstant","$mdUtil","$mdComponentRegistry","$timeout","$q","$animate","$parse",o]};return t}angular.module("material.components.expansionPanels").directive("mdExpansionPanel",n);var e=180}(),function(){"use strict";function n(n,e,o){function t(t){var i=n.get(t);return i?i:void o.error(e.supplant(r,[t||""]))}function i(e){return n.when(e)["catch"](o.error)}var r="ExpansionPanel '{0}' is not available! Did you use md-component-id='{0}'?",a={find:t,waitFor:i};return function(n){return void 0===n?a:t(n)}}angular.module("material.components.expansionPanels").factory("$mdExpansionPanel",n),n.$inject=["$mdComponentRegistry","$mdUtil","$log"]}(),function(){"use strict";function n(n,e){function o(o,t,i,r){function a(e){t.css("width",t[0].offsetWidth+"px"),r.$element.css("min-height",t[0].offsetHeight+"px");var o={addClass:"md-absolute md-hide",from:{opacity:1},to:{opacity:0}};e.animation===!1&&(o.duration=0),n(t,o).start().then(function(){t.removeClass("md-hide"),t.css("display","none")})}function s(o){t.css("display",""),t.css("width",t[0].parentNode.offsetWidth+"px");var i={addClass:"md-show",from:{opacity:0},to:{opacity:1}};o.animation===!1&&(i.duration=0),n(t,i).start().then(function(){r.$element.css("transition","none"),t.removeClass("md-absolute md-show"),t.css("width",""),r.$element.css("min-height",""),e(function(){r.$element.css("transition","")},0)})}r.registerCollapsed({show:s,hide:a}),t.on("click",function(){r.expand()})}var t={restrict:"E",require:"^^mdExpansionPanel",link:o};return t}angular.module("material.components.expansionPanels").directive("mdExpansionPanelCollapsed",n),n.$inject=["$animateCss","$timeout"]}(),function(){"use strict";function n(n,e){function o(o,t,i,r){function a(e){var o=l?l:t[0].scrollHeight+"px";t.addClass("md-hide md-overflow"),t.removeClass("md-show md-scroll-y");var i={from:{"max-height":o,opacity:1},to:{"max-height":"48px",opacity:0}};e.animation===!1&&(i.duration=0),n(t,i).start().then(function(){t.css("display","none"),t.removeClass("md-hide")})}function s(o){t.css("display",""),t.addClass("md-show md-overflow");var i=l?l:t[0].scrollHeight+"px",r={from:{"max-height":"48px",opacity:0},to:{"max-height":i,opacity:1}};o.animation===!1&&(r.duration=0),n(t,r).start().then(function(){void 0!==l?t.addClass("md-scroll-y"):(t.css("transition","none"),t.css("max-height","none"),e(function(){t.css("transition","")},0)),t.removeClass("md-overflow")})}var l=i.height||void 0;void 0!==l&&(l=l.replace("px","")+"px"),r.registerExpanded({show:s,hide:a,setHeight:void 0!==l,$element:t})}var t={restrict:"E",require:"^^mdExpansionPanel",link:o};return t}angular.module("material.components.expansionPanels").directive("mdExpansionPanelExpanded",n),n.$inject=["$animateCss","$timeout"]}(),function(){"use strict";function n(){function n(n,e,o,t){function i(){}function r(){l()}function a(n,o,i){var r,a,s=e[0].getBoundingClientRect();s.bottom>o?(r=u[0].offsetHeight,a=o-r-i,a