UNPKG

angular-material-npfixed

Version:

The Angular Material project is an implementation of Material Design in Angular.js. This project provides a set of reusable, well-tested, and accessible Material Design UI components. Angular Material is supported internally at Google by the Angular.js, M

864 lines (749 loc) 22.6 kB
angular.module('docsApp', [ 'angularytics', 'ngRoute', 'ngMessages', 'ngMaterial' ], [ 'SERVICES', 'COMPONENTS', 'DEMOS', 'PAGES', '$routeProvider', '$locationProvider', '$mdThemingProvider', '$mdIconProvider', function(SERVICES, COMPONENTS, DEMOS, PAGES, $routeProvider, $locationProvider, $mdThemingProvider, $mdIconProvider) { $locationProvider.html5Mode(true); $routeProvider .when('/', { templateUrl: 'partials/home.tmpl.html' }) .when('/layout/:tmpl', { templateUrl: function(params){ return 'partials/layout-' + params.tmpl + '.tmpl.html'; } }) .when('/layout/', { redirectTo: '/layout/introduction' }) .when('/demo/', { redirectTo: DEMOS[0].url }) .when('/api/', { redirectTo: COMPONENTS[0].docs[0].url }) .when('/getting-started', { templateUrl: 'partials/getting-started.tmpl.html' }) .when('/contributors', { templateUrl: 'partials/contributors.tmpl.html' }) .when('/license', { templateUrl: 'partials/license.tmpl.html' }); $mdThemingProvider.definePalette('docs-blue', $mdThemingProvider.extendPalette('blue', { '50': '#DCEFFF', '100': '#AAD1F9', '200': '#7BB8F5', '300': '#4C9EF1', '400': '#1C85ED', '500': '#106CC8', '600': '#0159A2', '700': '#025EE9', '800': '#014AB6', '900': '#013583', 'contrastDefaultColor': 'light', 'contrastDarkColors': '50 100 200 A100', 'contrastStrongLightColors': '300 400 A200 A400' })); $mdThemingProvider.definePalette('docs-red', $mdThemingProvider.extendPalette('red', { 'A100': '#DE3641' })); $mdThemingProvider.theme('docs-dark', 'default') .primaryPalette('yellow') .dark(); $mdIconProvider.icon('md-toggle-arrow', 'img/icons/toggle-arrow.svg', 48); $mdThemingProvider.theme('default') .primaryPalette('docs-blue') .accentPalette('docs-red'); $mdThemingProvider .enableBrowserColor(); angular.forEach(PAGES, function(pages, area) { angular.forEach(pages, function(page) { $routeProvider .when(page.url, { templateUrl: page.outputPath, controller: 'GuideCtrl' }); }); }); angular.forEach(COMPONENTS, function(component) { angular.forEach(component.docs, function(doc) { $routeProvider.when('/' + doc.url, { templateUrl: doc.outputPath, resolve: { component: function() { return component; }, doc: function() { return doc; } }, controller: 'ComponentDocCtrl' }); }); }); angular.forEach(SERVICES, function(service) { $routeProvider.when('/' + service.url, { templateUrl: service.outputPath, resolve: { component: function() { return { isService: true } }, doc: function() { return service; } }, controller: 'ComponentDocCtrl' }); }); angular.forEach(DEMOS, function(componentDemos) { var demoComponent; COMPONENTS.forEach(function(component) { if (componentDemos.moduleName === component.name) { demoComponent = component; component.demoUrl = componentDemos.url; } }); demoComponent = demoComponent || angular.extend({}, componentDemos); $routeProvider.when('/' + componentDemos.url, { templateUrl: 'partials/demo.tmpl.html', controller: 'DemoCtrl', resolve: { component: function() { return demoComponent; }, demos: function() { return componentDemos.demos; } } }); }); $routeProvider.otherwise('/'); // Change hash prefix of the Angular router, because we use the hash symbol for anchor links. // The hash will be not used by the docs, because we use the HTML5 mode for our links. $locationProvider.hashPrefix('!'); }]) .config(['AngularyticsProvider', function(AngularyticsProvider) { AngularyticsProvider.setEventHandlers(['Console', 'GoogleUniversal']); }]) .run(['Angularytics', function(Angularytics) { Angularytics.init(); }]) .factory('menu', [ 'SERVICES', 'COMPONENTS', 'DEMOS', 'PAGES', '$location', '$rootScope', '$http', '$window', function(SERVICES, COMPONENTS, DEMOS, PAGES, $location, $rootScope, $http, $window) { var version = {}; var sections = [{ name: 'Getting Started', url: 'getting-started', type: 'link' }]; var demoDocs = []; angular.forEach(DEMOS, function(componentDemos) { demoDocs.push({ name: componentDemos.label, url: componentDemos.url }); }); sections.push({ name: 'Demos', pages: demoDocs.sort(sortByName), type: 'toggle' }); sections.push(); sections.push({ name: 'Customization', type: 'heading', children: [ { name: 'CSS', type: 'toggle', pages: [{ name: 'Typography', url: 'CSS/typography', type: 'link' }, { name : 'Button', url: 'CSS/button', type: 'link' }, { name : 'Checkbox', url: 'CSS/checkbox', type: 'link' }] }, { name: 'Theming', type: 'toggle', pages: [ { name: 'Introduction and Terms', url: 'Theming/01_introduction', type: 'link' }, { name: 'Declarative Syntax', url: 'Theming/02_declarative_syntax', type: 'link' }, { name: 'Configuring a Theme', url: 'Theming/03_configuring_a_theme', type: 'link' }, { name: 'Multiple Themes', url: 'Theming/04_multiple_themes', type: 'link' }, { name: 'Under the Hood', url: 'Theming/05_under_the_hood', type: 'link' }, { name: 'Browser Color', url: 'Theming/06_browser_color', type: 'link' } ] } ] }); var docsByModule = {}; var apiDocs = {}; COMPONENTS.forEach(function(component) { component.docs.forEach(function(doc) { if (angular.isDefined(doc.private)) return; apiDocs[doc.type] = apiDocs[doc.type] || []; apiDocs[doc.type].push(doc); docsByModule[doc.module] = docsByModule[doc.module] || []; docsByModule[doc.module].push(doc); }); }); SERVICES.forEach(function(service) { if (angular.isDefined(service.private)) return; apiDocs[service.type] = apiDocs[service.type] || []; apiDocs[service.type].push(service); docsByModule[service.module] = docsByModule[service.module] || []; docsByModule[service.module].push(service); }); sections.push({ name: 'API Reference', type: 'heading', children: [ { name: 'Layout', type: 'toggle', pages: [{ name: 'Introduction', id: 'layoutIntro', url: 'layout/introduction' } ,{ name: 'Layout Containers', id: 'layoutContainers', url: 'layout/container' } ,{ name: 'Layout Children', id: 'layoutGrid', url: 'layout/children' } ,{ name: 'Child Alignment', id: 'layoutAlign', url: 'layout/alignment' } ,{ name: 'Extra Options', id: 'layoutOptions', url: 'layout/options' } ,{ name: 'Troubleshooting', id: 'layoutTips', url: 'layout/tips' }] }, { name: 'Services', pages: apiDocs.service.sort(sortByName), type: 'toggle' },{ name: 'Types', pages: apiDocs.type.sort(sortByName), type: 'toggle' },{ name: 'Directives', pages: apiDocs.directive.sort(sortByName), type: 'toggle' }] }); sections.push( { name: 'Contributors', url: 'contributors', type: 'link' } ); sections.push({ name: 'License', url: 'license', type: 'link', // Add a hidden section so that the title in the toolbar is properly set hidden: true }); function sortByName(a,b) { return a.name < b.name ? -1 : 1; } var self; $rootScope.$on('$locationChangeSuccess', onLocationChange); $http.get("/docs.json") .then(function(response) { var versionId = getVersionIdFromPath(); var head = { type: 'version', url: '/HEAD', id: 'head', name: 'HEAD (master)', github: '' }; var commonVersions = versionId === 'head' ? [] : [ head ]; var knownVersions = getAllVersions(); var listVersions = knownVersions.filter(removeCurrentVersion); var currentVersion = getCurrentVersion() || {name: 'local'}; version.current = currentVersion; sections.unshift({ name: 'Documentation Version', type: 'heading', className: 'version-picker', children: [ { name: currentVersion.name, type: 'toggle', pages: commonVersions.concat(listVersions) } ] }); function removeCurrentVersion (version) { switch (versionId) { case version.id: return false; case 'latest': return !version.latest; default: return true; } } function getAllVersions () { if (response && response.versions && response.versions.length) { return response.versions.map(function(version) { var latest = response.latest === version; return { type: 'version', url: '/' + version, name: getVersionFullString({ id: version, latest: latest }), id: version, latest: latest, github: 'tree/v' + version }; }); } return []; } function getVersionFullString (version) { return version.latest ? 'Latest Release (' + version.id + ')' : 'Release ' + version.id; } function getCurrentVersion () { switch (versionId) { case 'head': return head; case 'latest': return knownVersions.filter(getLatest)[0]; default: return knownVersions.filter(getVersion)[0]; } function getLatest (version) { return version.latest; } function getVersion (version) { return versionId === version.id; } } function getVersionIdFromPath () { var path = $window.location.pathname; if (path.length < 2) path = 'HEAD'; return path.match(/[^\/]+/)[0].toLowerCase(); } }); return self = { version: version, sections: sections, selectSection: function(section) { self.openedSection = section; }, toggleSelectSection: function(section) { self.openedSection = (self.openedSection === section ? null : section); }, isSectionSelected: function(section) { return self.openedSection === section; }, selectPage: function(section, page) { self.currentSection = section; self.currentPage = page; }, isPageSelected: function(page) { return self.currentPage === page; } }; function onLocationChange() { var path = $location.path(); var introLink = { name: "Introduction", url: "/", type: "link" }; if (path == '/') { self.selectSection(introLink); self.selectPage(introLink, introLink); return; } var matchPage = function(section, page) { if (path.indexOf(page.url) !== -1) { self.selectSection(section); self.selectPage(section, page); } }; sections.forEach(function(section) { if (section.children) { // matches nested section toggles, such as API or Customization section.children.forEach(function(childSection){ if(childSection.pages){ childSection.pages.forEach(function(page){ matchPage(childSection, page); }); } }); } else if (section.pages) { // matches top-level section toggles, such as Demos section.pages.forEach(function(page) { matchPage(section, page); }); } else if (section.type === 'link') { // matches top-level links, such as "Getting Started" matchPage(section, section); } }); } }]) .directive('menuLink', function() { return { scope: { section: '=' }, templateUrl: 'partials/menu-link.tmpl.html', link: function($scope, $element) { var controller = $element.parent().controller(); $scope.isSelected = function() { return controller.isSelected($scope.section); }; $scope.focusSection = function() { // set flag to be used later when // $locationChangeSuccess calls openPage() controller.autoFocusContent = true; }; } }; }) .directive('menuToggle', ['$mdUtil', '$animateCss', '$$rAF', function($mdUtil, $animateCss, $$rAF) { return { scope: { section: '=' }, templateUrl: 'partials/menu-toggle.tmpl.html', link: function($scope, $element) { var controller = $element.parent().controller(); // Used for toggling the visibility of the accordion's content, after // all of the animations are completed. This prevents users from being // allowed to tab through to the hidden content. $scope.renderContent = false; $scope.isOpen = function() { return controller.isOpen($scope.section); }; $scope.toggle = function() { controller.toggleOpen($scope.section); }; $mdUtil.nextTick(function() { $scope.$watch(function () { return controller.isOpen($scope.section); }, function (open) { var $ul = $element.find('ul'); var $li = $ul[0].querySelector('a.active'); if (open) { $scope.renderContent = true; } $$rAF(function() { var targetHeight = open ? $ul[0].scrollHeight : 0; $animateCss($ul, { easing: 'cubic-bezier(0.35, 0, 0.25, 1)', to: { height: targetHeight + 'px' }, duration: 0.75 // seconds }).start().then(function() { var $li = $ul[0].querySelector('a.active'); $scope.renderContent = open; if (open && $li && $ul[0].scrollTop === 0) { var activeHeight = $li.scrollHeight; var activeOffset = $li.offsetTop; var offsetParent = $li.offsetParent; var parentScrollPosition = offsetParent ? offsetParent.offsetTop : 0; // Reduce it a bit (2 list items' height worth) so it doesn't touch the nav var negativeOffset = activeHeight * 2; var newScrollTop = activeOffset + parentScrollPosition - negativeOffset; $mdUtil.animateScrollTo(document.querySelector('.docs-menu').parentNode, newScrollTop); } }); }); }); }); var parentNode = $element[0].parentNode.parentNode.parentNode; if(parentNode.classList.contains('parent-list-item')) { var heading = parentNode.querySelector('h2'); $element[0].firstChild.setAttribute('aria-describedby', heading.id); } } }; }]) .controller('DocsCtrl', [ '$scope', 'COMPONENTS', 'BUILDCONFIG', '$mdSidenav', '$timeout', '$mdDialog', 'menu', '$location', '$rootScope', '$mdUtil', function($scope, COMPONENTS, BUILDCONFIG, $mdSidenav, $timeout, $mdDialog, menu, $location, $rootScope, $mdUtil) { var self = this; $scope.COMPONENTS = COMPONENTS; $scope.BUILDCONFIG = BUILDCONFIG; $scope.menu = menu; $scope.path = path; $scope.goHome = goHome; $scope.openMenu = openMenu; $scope.closeMenu = closeMenu; $scope.isSectionSelected = isSectionSelected; $scope.scrollTop = scrollTop; // Grab the current year so we don't have to update the license every year $scope.thisYear = (new Date()).getFullYear(); $rootScope.$on('$locationChangeSuccess', openPage); $scope.focusMainContent = focusMainContent; //-- Define a fake model for the related page selector Object.defineProperty($rootScope, "relatedPage", { get: function () { return null; }, set: angular.noop, enumerable: true, configurable: true }); $rootScope.redirectToUrl = function(url) { $location.path(url); $timeout(function () { $rootScope.relatedPage = null; }, 100); }; // Methods used by menuLink and menuToggle directives this.isOpen = isOpen; this.isSelected = isSelected; this.toggleOpen = toggleOpen; this.autoFocusContent = false; var mainContentArea = document.querySelector("[role='main']"); var scrollContentEl = mainContentArea.querySelector('md-content[md-scroll-y]'); // ********************* // Internal methods // ********************* function closeMenu() { $timeout(function() { $mdSidenav('left').close(); }); } function openMenu() { $timeout(function() { $mdSidenav('left').open(); }); } function path() { return $location.path(); } function scrollTop() { $mdUtil.animateScrollTo(scrollContentEl, 0, 200); } function goHome($event) { menu.selectPage(null, null); $location.path( '/' ); } function openPage() { $scope.closeMenu(); if (self.autoFocusContent) { focusMainContent(); self.autoFocusContent = false; } } function focusMainContent($event) { // prevent skip link from redirecting if ($event) { $event.preventDefault(); } $timeout(function(){ mainContentArea.focus(); },90); } function isSelected(page) { return menu.isPageSelected(page); } function isSectionSelected(section) { var selected = false; var openedSection = menu.openedSection; if(openedSection === section){ selected = true; } else if(section.children) { section.children.forEach(function(childSection) { if(childSection === openedSection){ selected = true; } }); } return selected; } function isOpen(section) { return menu.isSectionSelected(section); } function toggleOpen(section) { menu.toggleSelectSection(section); } }]) .controller('HomeCtrl', [ '$scope', '$rootScope', function($scope, $rootScope) { $rootScope.currentComponent = $rootScope.currentDoc = null; }]) .controller('GuideCtrl', [ '$rootScope', '$http', function($rootScope, $http) { $rootScope.currentComponent = $rootScope.currentDoc = null; if ( !$rootScope.contributors ) { $http .get('./contributors.json') .then(function(response) { $rootScope.github = response.data; }) } }]) .controller('LayoutCtrl', [ '$scope', '$attrs', '$location', '$rootScope', function($scope, $attrs, $location, $rootScope) { $rootScope.currentComponent = $rootScope.currentDoc = null; $scope.exampleNotEditable = true; $scope.layoutDemo = { mainAxis: 'center', crossAxis: 'center', direction: 'row' }; $scope.layoutAlign = function() { return $scope.layoutDemo.mainAxis + ($scope.layoutDemo.crossAxis ? ' ' + $scope.layoutDemo.crossAxis : '') }; }]) .controller('LayoutTipsCtrl', [ function() { var self = this; /* * Flex Sizing - Odd */ self.toggleButtonText = "Hide"; self.toggleContentSize = function() { var contentEl = angular.element(document.getElementById('toHide')); contentEl.toggleClass("ng-hide"); self.toggleButtonText = contentEl.hasClass("ng-hide") ? "Show" : "Hide"; }; }]) .controller('ComponentDocCtrl', [ '$scope', 'doc', 'component', '$rootScope', function($scope, doc, component, $rootScope) { $rootScope.currentComponent = component; $rootScope.currentDoc = doc; }]) .controller('DemoCtrl', [ '$rootScope', '$scope', 'component', 'demos', '$templateRequest', function($rootScope, $scope, component, demos, $templateRequest) { $rootScope.currentComponent = component; $rootScope.currentDoc = null; $scope.demos = []; angular.forEach(demos, function(demo) { // Get displayed contents (un-minified) var files = [demo.index] .concat(demo.js || []) .concat(demo.css || []) .concat(demo.html || []); files.forEach(function(file) { file.httpPromise = $templateRequest(file.outputPath) .then(function(response) { file.contents = response .replace('<head/>', ''); return file.contents; }); }); demo.$files = files; $scope.demos.push(demo); }); $scope.demos = $scope.demos.sort(function(a,b) { return a.name > b.name ? 1 : -1; }); }]) .filter('nospace', function () { return function (value) { return (!value) ? '' : value.replace(/ /g, ''); }; }) .filter('humanizeDoc', function() { return function(doc) { if (!doc) return; if (doc.type === 'directive') { return doc.name.replace(/([A-Z])/g, function($1) { return '-'+$1.toLowerCase(); }); } return doc.label || doc.name; }; }) .filter('directiveBrackets', function() { return function(str, restrict) { if (restrict) { // If it is restricted to only attributes if (!restrict.element && restrict.attribute) { return '[' + str + ']'; } // If it is restricted to elements and isn't a service if (restrict.element && str.indexOf('-') > -1) { return '<' + str + '>'; } // TODO: Handle class/comment restrictions if we ever have any to document } // Just return the original string if we don't know what to do with it return str; }; }) /** Directive which applies a specified class to the element when being scrolled */ .directive('docsScrollClass', function() { return { restrict: 'A', link: function(scope, element, attr) { var scrollParent = element.parent(); var isScrolling = false; // Initial update of the state. updateState(); // Register a scroll listener, which updates the state. scrollParent.on('scroll', updateState); function updateState() { var newState = scrollParent[0].scrollTop !== 0; if (newState !== isScrolling) { element.toggleClass(attr.docsScrollClass, newState); } isScrolling = newState; } } }; });