Angular Foundation 6

With love, from Pinecone


Download v0.11.22 Contribute

Dependencies

This repository contains a set of native AngularJS directives based on Foundation's markup and CSS. As a result no dependency on jQuery or Foundation's JavaScript is required. The only required dependencies are:

  • AngularJS 1.5 (tested with 1.5.10)
  • Foundation 6 CSS (tested with version 6.4.3).

Downloading

Build files for all directives are distributed in several flavours: minified for production usage, un-minified for development, with or without templates. All the options are described and can be downloaded from here.

Installation

As soon as you've got all the files downloaded and included in your page you just need to declare a dependency on the mm.foundation module:

angular.module('myModule', ['mm.foundation']);

You can fork one of the plunkers from this page to see a working example of what is described here.


This content is straight in the template. {{group.content}}

The body of the accordion group grows to fit the contents

{{item}}
I can have markup, too! This is just some content to illustrate fancy headings.

The accordion directive builds on top of the collapse directive to provide a list of items, with collapsible bodies that are collapsed or expanded by clicking on the item's header.

We can control whether expanding an item will cause the other items to close, using the close-others attribute on accordion.

The body of each accordion group is transcluded in to the body of the collapsible element.

<div ng-controller="AccordionDemoCtrl">
  <label class="checkbox">
    <input type="checkbox" ng-model="oneAtATime">
    Open only one at a time
  </label>

  <accordion close-others="oneAtATime">
    <accordion-group heading="Static Header, initially expanded" is-open="true">
      This content is straight in the template.
    </accordion-group>
    <accordion-group heading="{{group.title}}" ng-repeat="group in groups">
      {{group.content}}
    </accordion-group>
    <accordion-group heading="Dynamic Body Content">
      <p>The body of the accordion group grows to fit the contents</p>
        <button class="button small" ng-click="addItem()">Add Item</button>
        <div ng-repeat="item in items">{{item}}</div>
    </accordion-group>
    <accordion-group is-open="isopen">
        <accordion-heading>
            I can have markup, too!
        </accordion-heading>
        This is just some content to illustrate fancy headings.
    </accordion-group>
  </accordion>
</div>
angular.module('foundationDemoApp').controller('AccordionDemoCtrl', function($scope) {
    $scope.oneAtATime = true;

    $scope.groups = [{
        title: "Dynamic Group Header - 1",
        content: "Dynamic Group Body - 1"
    }, {
        title: "Dynamic Group Header - 2",
        content: "Dynamic Group Body - 2"
    }];

    $scope.items = ['Item 1', 'Item 2', 'Item 3'];

    $scope.addItem = function() {
        var newItemNo = $scope.items.length + 1;
        $scope.items.push('Item ' + newItemNo);
    };
});

{{alert.msg}}

Alert is an AngularJS-version of Foundation's alert.

This directive can be used to generate alerts from the dynamic model data (using the ng-repeat directive);

The presence of the "close" attribute determines if a close button is displayed

<div ng-controller="AlertDemoCtrl">
  <alert ng-repeat="alert in alerts" type="alert.type" close="closeAlert($index)">{{alert.msg}}</alert>
  <button class='button' ng-click="addAlert()">Add Alert</button>
</div>
angular.module('foundationDemoApp').controller('AlertDemoCtrl', function($scope) {
  $scope.alerts = [
    { type: 'alert', msg: 'Oh snap! Change a few things up and try submitting again.' },
    { type: 'success round', msg: 'Well done! You successfully read this important alert message.' }
  ];

  $scope.addAlert = function() {
    $scope.alerts.push({type: 'alert', msg: "Another alert!"});
  };

  $scope.closeAlert = function(index) {
    $scope.alerts.splice(index, 1);
  };

});

Single toggle

{{singleModel}}

Checkbox

{{checkModel}}

Radio

{{radioModel}}

There are 2 directives that can make a group of buttons to behave like a set of checkboxes or radio buttons.

<div ng-controller="ButtonsCtrl">
    <h4>Single toggle</h4>
    <pre>{{singleModel}}</pre>
    <button type="button" class="button" ng-model="singleModel" btn-checkbox btn-checkbox-true="1" btn-checkbox-false="0">
        Single Toggle
    </button>
    <h4>Checkbox</h4>
    <pre>{{checkModel}}</pre>
    <div class="button-group">
        <button type="button" class="button" ng-model="checkModel.left" btn-checkbox>Left</button>
        <button type="button" class="button" ng-model="checkModel.middle" btn-checkbox>Middle</button>
        <button type="button" class="button" ng-model="checkModel.right" btn-checkbox>Right</button>
    </div>
    <h4>Radio</h4>
    <pre>{{radioModel}}</pre>
    <div class="button-group">
        <button type="button" class="button" ng-model="radioModel" btn-radio="'Left'">Left</button>
        <button type="button" class="button" ng-model="radioModel" btn-radio="'Middle'">Middle</button>
        <button type="button" class="button" ng-model="radioModel" btn-radio="'Right'">Right</button>
    </div>
</div>
angular.module('foundationDemoApp').controller('ButtonsCtrl', function ($scope) {

  $scope.singleModel = 1;

  $scope.radioModel = 'Middle';

  $scope.checkModel = {
    left: false,
    middle: true,
    right: false
  };
});

A directive that provides the Foundation Drilldown Menu component.

The directive relies on the same markup as the original Foundation Drilldown Menu. It implements some, but not all of the features of the Foundation Drilldown Menu.

See the demo page for example on how to use this and visit the Foundation docs for more details.

Supported Features:

  • Automatically add a wrapper div around the menu, if not already provided in the html.
  • Automatically add back entries to the top of submenus, if not already provided in the html.
  • Wrapper div sized to the min-height required to show the largest sub-menu.
    • Automatically resizes as the viewport size changes.
    • WARNING: show/hide via ng-show or similar DOES NOT cause a resize. See notes below.
  • API exposed via drilldown-menu-api two-way binding.
  • Events emit-ed on the $scope (i.e. upwards towards parent scopes).

API

The API for programmatic control of the drilldown menu is exposed to the parent scope via the drilldown-menu-api two-way binding. See the 3rd example html and associated js for an example.

The available methods are:

  • resizeMenu() to trigger a resize.
  • show(element) to show the submenu under the given angular.element.
  • hide(element) to hide the submenu under the given angular.element.
  • hideAll() to collapse all submenus.

Events

The controller emit-s events on the $scope (i.e. upwards towards the parent scope). The available events are similarly named to the Foundation for Sites equivalents.

  • 'resize.mm.foundation.drilldownMenu' when the menu resizes. The event listener function format is function(event, menuElement):
  • 'open.mm.foundation.drilldownMenu' when a submenu is opened. The event listener function format is function(event, menuElement, submenuElement):
  • 'hide.mm.foundation.drilldownMenu' when a submenu is closed. The event listener function format is function(event, menuElement, submenuElement) as above.

Usage Notes

Be careful when dynamically showing and hiding this component. The component only resizes when created, when the viewport size changes, or when the resize() API is triggered. If it is hidden via css when created it will initialse with 0 height and width. If it is then shown (using ng-show or similar), it will remain as 0 height and width and thus not appear to be visible!

This can be resolved by using the API to resize as part of the reveal.

Alternatively, use ng-if instead of ng-show. This re-creates the component when showing, and thus the size is set correctly as part of the initialisation.

NOT implemented:

The following features of the Foundation Drilldown Menu are NOT implemented:

  • back entries at the bottom of submenus.
  • templates for auto-added back entries.
  • autoHeight.
  • ScrollTop.
  • Handling of keyboard events (up/down/etc.)
  • Automatic addition of aria attributes.
  • Any of the plugin options.
  • scrollme and closed events.
  • _scrollTop and _destroy methods.
<div ng-controller="DrillDownDemoCtrl">
  <div class="callout">
    <h4>Auto `Wrapper` and `Back` Links</h4>
    <ul class="drilldown menu" drilldown-menu>

      <li>
        <a>Item 1</a>
        <ul class="menu">
          <li><a href="#">Item 1A</a></li>
          <li>
            <a href="#">Item 1B</a>
            <ul class="menu">
              <li><a href="#">Item 1B i make this really long so that it will overflow a line</a></li>
              <li><a href="#">Item 1B ii</a></li>
              <li>
                <a href="#">Item 1B iii - this one is also extended to overflow a line</a>
                <ul class="menu">
                  <li><a href="#">Item 1B iii alpha</a></li>
                  <li><a href="#">Item 1B iii omega</a></li>
                </ul>
              </li>
              <li>
                <a href="#">Item 1B iv</a>
                <ul class="menu">
                  <li><a href="#">Item 1B iv alpha</a></li>
                </ul>
              </li>
            </ul>
          </li>
          <li><a href="#">Item 1C</a></li>
        </ul>
      </li>
      <li>
        <a href="#">Search Engines</a>
        <ul class="menu">
          <li><a href="https://www.google.com/">Google</a></li>
          <li><a href="https://www.bing.com/">Bing</a></li>
          <li><a href="https://www.duckduckgo.com/">DuckDuckGo</a></li>
        </ul>
      </li>
      <li><a href="http://foundation.zurb.com/">Foundation</a></li>
      <li><a href="#">Item 4</a></li>
    </ul>
  </div>

  <div class="callout">

    <!-- Manual Wrapper and Back Links -->
    <h4>Manual `Wrapper` and `Back` Links</h4>
    <!-- Manually added wrapper MUST be `div` with class `is-drilldown` -->
    <div class="is-drilldown">
      <ul class="drilldown menu" drilldown-menu>
        <li>
          <a>Item 1</a>
          <ul class="menu">
            <!-- Manual back link MUST be `li` with class `.js-drilldown-back` -->
            <li class="js-drilldown-back"><a href="#">Manual Back To Top</a></li>
            <li><a href="#">Item 1A</a></li>
            <li>
              <a href="#">Item 1B</a>
              <ul class="menu">
                <li class="js-drilldown-back"><a href="#">Manual Back To Level 1</a></li>
                <li><a href="#">Item 1B i</a></li>
                <li><a href="#">Item 1B ii</a></li>
              </ul>
            </li>
            <li><a href="#">Item 1C</a></li>
          </ul>
        </li>
        <li><a href="#">Item 2</a></li>
      </ul>
    </div>
  </div>

  <div class="callout" id="drilldown-api">

    <!-- API usage -->
    <h4>API Usage</h4>
    <alert ng-repeat="alert in vm.alerts" type="alert.type" close="vm.closeAlert($index)">
      {{alert.msg}}
    </alert>

    <div>
      <button class="button" ng-click="vm.showHideMenu()">Show / Hide the Menu</button>
      <button class="button" ng-click="vm.ddmApi.resizeMenu()" ng-show="vm.haveShown">Resize</button>
    </div>

    <div class="callout ng-hide" ng-show="vm.shouldShow">
      <ul class="drilldown menu" id="drilldown-api-menu" drilldown-menu drilldown-menu-api="vm.ddmApi">
        <li>
          <a href="#">Item 1</a>
          <ul class="menu" id="drilldown-api-submenu-1">
            <li><a href="#">Item 1A</a></li>
            <li>
              <a href="#">Item 1B</a>
              <ul class="menu">
                <li><a href="#">Item 1B i</a></li>
                <li><a href="#">Item 1B ii</a></li>
              </ul>
            </li>
            <li><a href="#">Item 1C</a></li>
          </ul>
        </li>
        <li><a href="#">Item 2</a></li>
      </ul>

      <div ng-show="vm.haveResized">
        <h5>Other API functions</h5>
        <button class="button" ng-click="vm.showSubmenu1()">Open Submenu 1</button>
        <button class="button" ng-click="vm.hideSubmenu1()">Close Submenu 1</button>
        <button class="button" ng-click="vm.ddmApi.hideAll()">Close All Submenus</button>
      </div>
    </div>
  </div>

</div>
angular.module('foundationDemoApp')
.controller('DrillDownDemoCtrl', function($scope, $element, $timeout, $log) {
    'ngInject';
    const vm = {
        ddmApi: null,
        shouldShow: false,
        haveShown: false,
        haveResized: false,
        alerts: [],

        showHideMenu: showHideMenu,

        showSubmenu1: showSubmenu1,
        hideSubmenu1: hideSubmenu1,

        closeAlert: closeAlert,
    };
    $scope.vm = vm;

    /**
     * Initial alert used as part of the API Usage demo
     */
    vm.alerts = [{
        type: 'alert',
        msg: 'The menu below is hidden with css. Press the button to show it (using ng-show).',
    }];

    /**
     * Event handlers for the menu events
     */
    $scope.$on('resize.mm.foundation.drilldownMenu', onMenuResized);
    $scope.$on('open.mm.foundation.drilldownMenu', onSubmenuOpen);
    $scope.$on('hide.mm.foundation.drilldownMenu', onSubmenuClosed);

    /**
     * Sets the variable to show or hide the menu block
     */
    function showHideMenu() {
        vm.shouldShow = !vm.shouldShow;

        if (!vm.haveShown) {
            closeAlert(0);
            addAlert(
                'alert',
                'The menu is now "shown", but because it was hidden initially it will start with ' +
                '"max-width: 0px" and doesn\'t appear! Press the resize button to trigger ' +
                'a resize via the API'
            );
            vm.haveShown = true;
        }
    }

    /**
     * Get the UL for submenu 1.
     * NOTE: You MUST use the UL for the submenu to show/hide, NOT the parent LI!
     *
     * @returns {angular.element}   - The element for submenu 1 in the API section
     */
    function getSubmenu1() {
        return angular.element($element[0].querySelector('ul#drilldown-api-submenu-1'));
    }

    /**
     * Function to use the API to open a specific menu item
     */
    function showSubmenu1() {
        //
        // Find the item
        //
        var element = getSubmenu1();

        //
        // Use the API to open it
        //
        vm.ddmApi.show(element);
    }

    /**
     * Function to use the API to close a specific menu item
     */
    function hideSubmenu1() {
        //
        // Find the item
        //
        var element = getSubmenu1();

        //
        // Use the API to open it
        //
        vm.ddmApi.hide(element);
    }

    /**
     * Handler for the resized event from the menu
     *
     * @param {Object} event                - Angular `event` object (see $rootScope.$on)
     * @param {angular.element} menuElement - The root element of the menu
     */
    function onMenuResized(event, menuElement) {
        if (menuElement.attr('id') !== 'drilldown-api-menu') {
            return; // One of the other menus
        }
        if (vm.haveShown && !vm.haveResized) {
            closeAlert(0);
            addAlert(
                'success',
                'Congratulations! The menu should now be visible!'
            );
            addAlert(
                'alert',
                'The same 0-width problem will happen again if the menu is hidden then ' +
                'resized (via the API or via a viewport size change). ' +
                'You MUST trigger a resize via the API after showing it again if this happens.'
            );
            vm.haveResized = true;
        }
    }

    /**
     * Example handler for the submenu open event
     *
     * @param {Object} event                    - Angular `event` object (see $rootScope.$on)
     * @param {angular.element} menuElement     - The root element of the menu
     * @param {angular.element} submenuElement  - The submenu element that has just opened
     */
    function onSubmenuOpen(event, menuElement, submenuElement) {
        if (submenuElement.attr('id') === 'drilldown-api-submenu-1') {
            $log.log('Submenu 1 has been opened!');
        }
    }

    /**
     * Example handler for the submenu close event
     *
     * @param {Object} event                    - Angular `event` object (see $rootScope.$on)
     * @param {angular.element} menuElement     - The root element of the menu
     * @param {angular.element} submenuElement  - The submenu element that has just closed
     */
    function onSubmenuClosed(event, menuElement, submenuElement) {
        if (submenuElement.attr('id') === 'drilldown-api-submenu-1') {
            $log.log('Submenu 1 has been closed!');
        }
    }

    /**
     * Closes the specific alert
     *
     * @param {number} index    - The index of the alert to close
     */
    function closeAlert(index) {
        vm.alerts.splice(index, 1);
    }

    /**
     * Adds a new alert programmatically.
     * Used of the explanations of the drilldown menu API and functionality.
     *
     * @param {string} type     - the type of alert
     * @param {string} msg      - the alert message
     */
    function addAlert(type, msg) {
        vm.alerts.push({ type: type, msg: msg });
    }
});

Foundation

How to use

Just use the standard layout for an offcanvas page as documented in the foundation docs

As long as you include mm.foundation.offcanvas it should simply work

A lightweight directive that provides the Foundation Offcanvas component.

There are no settings. You simply need to include the foundation off canvas CSS component in your page.

The off canvas module expects the use of several nested elements with the following classes:

  • off-canvas-wrapper: The most outter page wrapper.
  • inner-wrapper: Second page wrapper nested directly inside off-canvas-wrapper.
  • left-off-canvas-toggle: Wraps the left off canvas menu.
  • right-off-canvas-toggle: Wraps the right off canvas menu.
  • exit-off-canvas: Occludes the main page content when an off canvas menu is visible. Hides the menu when clicked.
  • off-canvas-list: Contains off canvas menu items. Hides the menu after a nested link is clicked.

See the demo page for example on how to use this and see the Foundation docs for more details.

<div ng-controller="OffCanvasDemoCtrl">
    <div class="off-canvas-wrapper">
        <div class="off-canvas-wrapper-inner">
            <div class="title-bar">
                <div class="title-bar-left">
                    <a class="left-off-canvas-toggle menu-icon" ><span></span></a>
                    <span class="title-bar-title">Foundation</span>
                </div>

                <div class="title-bar-right">
                    <a class="right-off-canvas-toggle menu-icon" ><span></span></a>
                </div>
            </div>
            <div class="off-canvas position-left">
                <ul class="mobile-ofc vertical menu">
                    <li>
                      <a href="#">Link 1</a>
                      <ul class="submenu menu vertical">
                        <li><a href="#">Sublink 1</a></li>
                        <li><a href="#">Sublink 2</a></li>
                        <li><a href="#">Sublink 3</a></li>
                        <li><a href="#">Sublink 4</a></li>
                      </ul>
                    </li>

                    <li>
                      <a href="#">Link 2</a>
                      <ul class="submenu menu vertical">
                        <li><a href="#">Sublink 5</a></li>
                        <li><a href="#">Sublink 6</a></li>
                        <li><a href="#">Sublink 7</a></li>
                      </ul>
                    </li>

                    <li><a href="#" class="button">Button 1</a></li>
                </ul>
            </div>
            <div class="off-canvas position-right">
                <ul class="mobile-ofc vertical menu">
                    <li>
                      <a href="#">Link 1</a>
                      <ul class="submenu menu vertical">
                        <li><a href="#">Sublink 1</a></li>
                        <li><a href="#">Sublink 2</a></li>
                        <li><a href="#">Sublink 3</a></li>
                        <li><a href="#">Sublink 4</a></li>
                      </ul>
                    </li>

                    <li>
                      <a href="#">Link 2</a>
                      <ul class="submenu menu vertical">
                        <li><a href="#">Sublink 5</a></li>
                        <li><a href="#">Sublink 6</a></li>
                        <li><a href="#">Sublink 7</a></li>
                      </ul>
                    </li>

                    <li><a href="#" class="button">Button 1</a></li>
                </ul>
            </div>
            <div class="off-canvas-content">
                <div class="small-12 columns">
                    <h1>How to use</h1>
                    <p>Just use the standard layout for an offcanvas page as documented in the <a href="http://foundation.zurb.com/docs/components/offcanvas.html">foundation docs</a></p>
                    <p>As long as you include mm.foundation.offcanvas it should simply work</p>
                </div>
            </div>
        </div>
    </div>
</div>
angular.module('foundationDemoApp').controller('OffCanvasDemoCtrl', function ($scope) {

});

< >
  • Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
  • Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
  • Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
  • Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

Beta version of the orbit directive.

<div ng-controller="OrbitDemoCtrl">
  <div class="orbit">
    <div class="orbit-wrapper">
      <div class="orbit-controls">
        <span class="orbit-previous"><</span>
        <span class="orbit-next">></span>
      </div>

      <ul class="orbit-container" style="height: auto">
        <li class="orbit-slide is-active">
          <div style="background-color: #20b2aa; padding: 2rem 4rem; color: #fefefe;">
            Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
          </div>
        </li>
        <li class="orbit-slide">
          <div style="background-color: #663399; padding: 2rem 4rem; color: #fefefe;">
            Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
          </div>
        </li>
        <li class="orbit-slide">
          <div style="background-color: #b8860b; padding: 2rem 4rem; color: #fefefe;">
            Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
          </div>
        </li>
        <li class="orbit-slide">
          <div style="background-color: #16b80b; padding: 2rem 4rem; color: #fefefe;">
            Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
          </div>
        </li>
      </ul>
    </div>

    <nav class="orbit-bullets"></nav>
  </div>
</div>
angular.module('foundationDemoApp').controller('OrbitDemoCtrl', function ($scope) {

});

Default

The selected page no: {{currentPage}}

Pager


Limit the maximum visible buttons

Page: {{bigCurrentPage}} / {{numPages}}

A lightweight pagination directive that is focused on ... providing pagination & will take care of visualising a pagination bar and enable / disable buttons correctly!

Pagination Settings

Settings can be provided as attributes in the <pagination> or globally configured through the paginationConfig.

  • page : Current page number. First page is 1.

  • total-items : Total number of items in all pages.

  • items-per-page (Defaults: 10) : Maximum number of items per page. A value less than one indicates all items on one page.

  • max-size (Defaults: null) : Limit number for pagination size.

  • num-pages readonly (Defaults: angular.noop) : An optional expression assigned the total number of pages to display.

  • rotate (Defaults: true) : Whether to keep current page in the middle of the visible ones.

  • on-select-page (page) (Default: null) : An optional expression called when a page is selected having the page number as argument.

  • direction-links (Default: true) : Whether to display Previous / Next buttons.

  • previous-text (Default: 'Previous') : Text for Previous button.

  • next-text (Default: 'Next') : Text for Next button.

  • boundary-links (Default: false) : Whether to display First / Last buttons.

  • first-text (Default: 'First') : Text for First button.

  • last-text (Default: 'Last') : Text for Last button.

Pager Settings

Settings can be provided as attributes in the <pager> or globally configured through the pagerConfig.
For page, total-items, items-per-page, num-pages and on-select-page (page) see pagination settings. Other settings are:

  • align (Default: true) : Whether to align each link to the sides.

  • previous-text (Default: '« Previous') : Text for Previous button.

  • next-text (Default: 'Next »') : Text for Next button.

<div ng-controller="PaginationDemoCtrl">
    <h4>Default</h4>
    <pagination total-items="totalItems" page="currentPage"></pagination>
    <pagination boundary-links="true" total-items="totalItems" page="currentPage" class="pagination-sm" previous-text="&lsaquo;" next-text="&rsaquo;" first-text="&laquo;" last-text="&raquo;"></pagination>
    <pagination direction-links="false" boundary-links="true" total-items="totalItems" page="currentPage"></pagination>
    <pagination direction-links="false" total-items="totalItems" page="currentPage" num-pages="smallnumPages"></pagination>
    <pre>The selected page no: {{currentPage}}</pre>
    <button class="button secondary" ng-click="setPage(3)">Set current page to: 3</button>

    <hr />
    <h4>Pager</h4>
    <pager total-items="totalItems" page="currentPage"></pager>

    <hr />
    <h4>Limit the maximum visible buttons</h4>
    <pagination total-items="bigTotalItems" page="bigCurrentPage" max-size="maxSize" class="pagination-sm" boundary-links="true"></pagination>
    <pagination total-items="bigTotalItems" page="bigCurrentPage" max-size="maxSize" class="pagination-sm" boundary-links="true" rotate="false" num-pages="numPages"></pagination>
    <pre>Page: {{bigCurrentPage}} / {{numPages}}</pre>
</div>
angular.module('foundationDemoApp').controller('PaginationDemoCtrl', function ($scope) {
  $scope.totalItems = 64;
  $scope.currentPage = 4;
  $scope.maxSize = 5;
  
  $scope.setPage = function (pageNo) {
    $scope.currentPage = pageNo;
  };

  $scope.bigTotalItems = 175;
  $scope.bigCurrentPage = 1;
});

Static

22%
166 / 200

Dynamic

{{dynamic}} / {{max}} No animation {{dynamic}}% Object (changes type based on value) {{type}} !!! Watch out !!!

A progress bar directive that is focused on providing feedback on the progress of a workflow or action.

It supports multiple (stacked) bars into the same <progress> element or a single <progressbar> element with optional max attribute and transition animations.

Settings

<progressbar>

  • value : The current value of progress completed.

  • type (Default: null) : Style type. Possible values are 'success', 'warning' etc.

  • max (Default: 100) : A number that specifies the total value of bars that is required.

  • animate (Default: true) : Whether bars use transitions to achieve the width change. IMPORTANT: Foundation's CSS does not not apply a transition to progress bars. In order for animations to work, you'll need to apply a transition in your own CSS. See the demo for an example.

<div ng-controller="ProgressDemoCtrl">
    <h3>Static</h3>
    <div class="row">
        <div class="columns small-4"><progressbar value="55"></progressbar></div>
        <div class="columns small-4"><progressbar value="22" type="warning">22%</progressbar></div>
        <div class="columns small-4"><progressbar max="200" value="166" type="alert">166 / 200</progressbar></div>
    </div>

    <hr />
    <h3>Dynamic <button class="button small" type="button" ng-click="random()">Randomize</button></h3>
    <progressbar max="max" value="dynamic">{{dynamic}} / {{max}}</progressbar>

    <small><em>No animation</em></small>
    <progressbar animate="false" value="dynamic" type="success">{{dynamic}}%</progressbar>

    <small><em>Object (changes type based on value)</em></small>
    <progressbar class="progress-striped active" value="dynamic" type="{{type}}">{{type}} <i ng-show="showWarning">!!! Watch out !!!</i></progressbar>

</div>
angular.module('foundationDemoApp').controller('ProgressDemoCtrl', function ($scope) {
  
  $scope.max = 200;

  $scope.random = function() {
    var value = Math.floor((Math.random() * 100) + 1);
    var type;

    if (value < 25) {
      type = 'success';
    } else if (value < 50) {
      type = 'info';
    } else if (value < 75) {
      type = 'warning';
    } else {
      type = 'alert';
    }

    $scope.showWarning = (type === 'alert' || type === 'warning');

    $scope.dynamic = value;
    $scope.type = type;
  };
  $scope.random();
});

Default

{{percent}}%
Rate: {{rate}} - Readonly is: {{isReadonly}} - Hovering over: {{overStar || "none"}}

Custom icons

(Rate: {{x}})
(Rate: {{y}})

Rating directive that will take care of visualising a star rating bar.

It uses Font Awesome icons (http://fontawesome.io/) by default.

Settings

<rating>

  • value : The current rate.

  • max (Defaults: 5) : Changes the number of icons.

  • readonly (Defaults: false) : Prevent user's interaction.

  • on-hover(value) : An optional expression called when user's mouse is over a particular icon.

  • on-leave() : An optional expression called when user's mouse leaves the control altogether.

  • state-on (Defaults: null) : A variable used in template to specify the state (class, src, etc) for selected icons.

  • state-off (Defaults: null) : A variable used in template to specify the state for unselected icons.

  • rating-states (Defaults: null) : An array of objects defining properties for all icons. In default template, stateOn & stateOff property is used to specify the icon's class.

<div ng-controller="RatingDemoCtrl">
    <h4>Default</h4>
    <rating value="rate" max="max" readonly="isReadonly" on-hover="hoveringOver(value)" on-leave="overStar = null"></rating>
    <span class="label" ng-class="{'label-warning': percent<30, 'label-info': percent>=30 && percent<70, 'label-success': percent>=70}" ng-show="overStar && !isReadonly">{{percent}}%</span>

    <pre class="mm-foundation-rating-demo-pre">Rate: <b>{{rate}}</b> - Readonly is: <i>{{isReadonly}}</i> - Hovering over: <b>{{overStar || "none"}}</b></pre>

    <button class="button small alert" ng-click="rate = 0" ng-disabled="isReadonly">Clear</button>
    <button class="button small" ng-click="isReadonly = ! isReadonly">Toggle Readonly</button>
    <hr />

    <h4>Custom icons</h4>
    <div ng-init="x = 5">
      <rating value="x" max="15" state-on="'fa-check-circle'" state-off="'fa-check-circle-o'"></rating>
      <b>(<i>Rate:</i> {{x}})</b>
    </div>
    <div ng-init="y = 2">
      <rating value="y" rating-states="ratingStates"></rating>
      <b>(<i>Rate:</i> {{y}})</b>
    </div>
</div>
angular.module('foundationDemoApp').controller('RatingDemoCtrl', function ($scope) {
  $scope.rate = 7;
  $scope.max = 10;
  $scope.isReadonly = false;

  $scope.hoveringOver = function(value) {
    $scope.overStar = value;
    $scope.percent = 100 * (value / $scope.max);
  };

  $scope.ratingStates = [
    {stateOn: 'fa-check-circle', stateOff: 'fa-check-circle-o'},
    {stateOn: 'fa-star', stateOff: 'fa-start-o'},
    {stateOn: 'fa-heart', stateOff: 'fa-ban'},
    {stateOn: 'fa-heart'},
    {stateOff: 'fa-power-off'}
  ];
});

Select a tab by setting active binding to true:


Static content {{tab.content}} Alert! I've got an HTML heading, and a select callback. Pretty cool!
Vertical content 1 Vertical content 2

Foundation version of the tabs directive.

Settings

<tabset>

  • vertical (Defaults: false) : Whether tabs appear vertically stacked.

  • open-on-load (Defaults: true) : Whether to open an active tab automatically.

<tab>

  • heading or <tab-heading> : Heading text or HTML markup.

  • active (Defaults: false) : Whether tab is currently selected.

  • select() (Defaults: null) : An optional expression called when tab is activated.

<div ng-controller="TabsDemoCtrl">
  <p>Select a tab by setting active binding to true:</p>
  <p>
    <button class="button small" ng-click="tabs[0].active = true">Select second tab</button>
    <button class="button small" ng-click="tabs[1].active = true">Select third tab</button>
  </p>
  <hr />

  <tabset>
    <tab heading="Static title">Static content</tab>
    <tab ng-repeat="tab in tabs" heading="{{tab.title}}" active="tab.active">
      {{tab.content}}
    </tab>
    <tab select="alertMe()">
      <tab-heading>
        <i class="fa fa-bell"></i> Alert!
      </tab-heading>
      I've got an HTML heading, and a select callback. Pretty cool!
    </tab>
  </tabset>

  <hr />

  <tabset vertical="true" type="navType">
    <tab heading="Vertical 1">Vertical content 1</tab>
    <tab heading="Vertical 2">Vertical content 2</tab>
  </tabset>

  <hr />
</div>
angular.module('foundationDemoApp').controller('TabsDemoCtrl', function ($scope) {
  $scope.tabs = [
    { title:"Dynamic Title 1", content:"Dynamic content 1" },
    { title:"Dynamic Title 2", content:"Dynamic content 2" }
  ];

  $scope.alertMe = function() {
    setTimeout(function() {
      alert("You've selected the alert tab!");
    });
  };
});

Pellentesque {{dynamicTooltipText}}, sit amet venenatis urna cursus eget nunc scelerisque viverra mauris, in aliquam. Tincidunt lobortis feugiat vivamus at left eget arcu dictum varius duis at consectetur lorem. Vitae elementum curabitur right nunc sed velit dignissim sodales ut eu sem integer vitae. Turpis egestas bottom pharetra convallis posuere morbi leo urna, at elementum eu, facilisis sed odio morbi quis commodo odio. In cursus delayed turpis massa tincidunt dui ut.

I can even contain HTML. Check me out!

A lightweight, extensible directive for fancy tooltip creation. The tooltip directive supports multiple placements, and more.

There are two versions of the tooltip: tooltip and tooltip-html-unsafe. The former takes text only and will escape any HTML provided. The latter takes whatever HTML is provided and displays it in a tooltip; it called "unsafe" because the HTML is not sanitized. The user is responsible for ensuring the content is safe to put into the DOM!

The tooltip directives provide several optional attributes to control how they will display:

  • tooltip-placement: Where to place it? Defaults to "top", but also accepts "bottom", "left", "right".
  • tooltip-popup-delay: For how long should the user have to have the mouse over the element before the tooltip shows (in milliseconds)? Defaults to 0.
  • tooltip-trigger: What should trigger a show of the tooltip? Supports a space separated list of event names
  • tooltip-append-to-body: Should the tooltip be appended to $body instead of the parent element?

The tooltip directives require the $position service.

Triggers

The following show triggers are supported out of the box, along with their provided hide triggers:

  • mouseenter: mouseleave
  • click: click
  • focus: blur

For any non-supported value, the trigger will be used to both show and hide the tooltip.

$tooltipProvider

Through the $tooltipProvider, you can change the way tooltips and popovers behave by default; the attributes above always take precedence. The following methods are available:

  • setTriggers( obj ): Extends the default trigger mappings mentioned above with mappings of your own. E.g. { 'openTrigger': 'closeTrigger' }.
  • options( obj ): Provide a set of defaults for certain tooltip and popover attributes. Currently supports 'placement', 'popupDelay', and appendToBody. Here are the defaults:

    placement: 'top',
    popupDelay: 0,
    appendToBody: false
    
<div ng-controller="TooltipDemoCtrl">
    <div class="form-group">
      <label>Dynamic Tooltip Text</label>
      <input type="text" ng-model="dynamicTooltipText" class="form-control">
    </div>
    <div class="form-group">
      <label>Dynamic Tooltip Popup Text</label>
      <input type="text" ng-model="dynamicTooltip" class="form-control">
    </div>
    <p>
      Pellentesque <a href="#" class="has-tip" tooltip="{{dynamicTooltip}}">{{dynamicTooltipText}}</a>,
      sit amet venenatis urna cursus eget nunc scelerisque viverra mauris, in
      aliquam. Tincidunt lobortis feugiat vivamus at
      <a href="#" class="has-tip" tooltip-placement="left" tooltip="On the Left!">left</a> eget
      arcu dictum varius duis at consectetur lorem. Vitae elementum curabitur
      <a href="#" class="has-tip" tooltip-placement="right" tooltip="On the Right!">right</a>
      nunc sed velit dignissim sodales ut eu sem integer vitae. Turpis egestas
      <a href="#" class="has-tip" tooltip-placement="bottom" tooltip="On the Bottom!">bottom</a>
      pharetra convallis posuere morbi leo urna, at elementum eu, facilisis sed odio morbi quis commodo odio. In cursus
      <a href="#" class="has-tip" tooltip-popup-delay='1000' tooltip='appears with delay'>delayed</a> turpis massa tincidunt dui ut.
    </p>

    <p>
      I can even contain HTML. <a href="#" class="has-tip" tooltip-html-unsafe="{{htmlTooltip}}">Check me out!</a>
    </p>

    <form role="form">
      <div class="form-group">
        <label>Or use custom triggers, like focus: </label>
        <input type="text" value="Click me!" tooltip="See? Now click away..."  tooltip-trigger="focus" tooltip-placement="right" class="form-control" />
      </div>
    </form>
</div>
angular.module('foundationDemoApp').controller('TooltipDemoCtrl', function($scope) {
    $scope.dynamicTooltip = 'Hello, World!';
    $scope.dynamicTooltipText = 'dynamic';
    $scope.htmlTooltip = "I've been made <b>bold</b>!";
});
$motion-ui-classes: (
          chain: true,
          prefix: 'ng-',
          active: '-active',
        );

        @import 'motion-ui';

        .tooltip {
            @include mui-fade(
              $state: in,
              $duration: 0.25s,
              $delay: 0s
            );
        }

        .tooltip {
            @include mui-fade(
                $state: out,
                $from: 1,
                $to: 0,
                $duration: 0.25s,
                $delay: 0s
            );
        }

        .reveal-overlay {
            @include mui-fade($state: in);
        }

        .reveal-overlay {
            @include mui-fade(
                $state: out,
                $from: 1,
                $to: 0
            );
        }

        .reveal {
            @include mui-slide(
                $state: in, // Specify in or out
                $direction: down, // Can be top, right, bottom, or left
                $fade: true, // If true, the element fades simultaneously
                $duration: 0.25s,
                $timing: cubic-bezier,
                $delay: 0s
            );
        }

        .reveal {
            @include mui-zoom(
                $state: out,
                $from: 1,
                $to: 0,
                $duration: 0.25s
            );
        }