UNPKG

ionic-angular

Version:

[![Circle CI](https://circleci.com/gh/driftyco/ionic.svg?style=svg)](https://circleci.com/gh/driftyco/ionic)

207 lines (185 loc) 6.68 kB
/** * @ngdoc service * @name $ionicActionSheet * @module ionic * @description * The Action Sheet is a slide-up pane that lets the user choose from a set of options. * Dangerous options are highlighted in red and made obvious. * * There are easy ways to cancel out of the action sheet, such as tapping the backdrop or even * hitting escape on the keyboard for desktop testing. * * ![Action Sheet](http://ionicframework.com.s3.amazonaws.com/docs/controllers/actionSheet.gif) * * @usage * To trigger an Action Sheet in your code, use the $ionicActionSheet service in your angular controllers: * * ```js * angular.module('mySuperApp', ['ionic']) * .controller(function($scope, $ionicActionSheet, $timeout) { * * // Triggered on a button click, or some other target * $scope.show = function() { * * // Show the action sheet * var hideSheet = $ionicActionSheet.show({ * buttons: [ * { text: '<b>Share</b> This' }, * { text: 'Move' } * ], * destructiveText: 'Delete', * titleText: 'Modify your album', * cancelText: 'Cancel', * cancel: function() { // add cancel code.. }, * buttonClicked: function(index) { * return true; * } * }); * * // For example's sake, hide the sheet after two seconds * $timeout(function() { * hideSheet(); * }, 2000); * * }; * }); * ``` * */ IonicModule .factory('$ionicActionSheet', [ '$rootScope', '$compile', '$animate', '$timeout', '$ionicTemplateLoader', '$ionicPlatform', '$ionicBody', 'IONIC_BACK_PRIORITY', function($rootScope, $compile, $animate, $timeout, $ionicTemplateLoader, $ionicPlatform, $ionicBody, IONIC_BACK_PRIORITY) { return { show: actionSheet }; /** * @ngdoc method * @name $ionicActionSheet#show * @description * Load and return a new action sheet. * * A new isolated scope will be created for the * action sheet and the new element will be appended into the body. * * @param {object} options The options for this ActionSheet. Properties: * * - `[Object]` `buttons` Which buttons to show. Each button is an object with a `text` field. * - `{string}` `titleText` The title to show on the action sheet. * - `{string=}` `cancelText` the text for a 'cancel' button on the action sheet. * - `{string=}` `destructiveText` The text for a 'danger' on the action sheet. * - `{function=}` `cancel` Called if the cancel button is pressed, the backdrop is tapped or * the hardware back button is pressed. * - `{function=}` `buttonClicked` Called when one of the non-destructive buttons is clicked, * with the index of the button that was clicked and the button object. Return true to close * the action sheet, or false to keep it opened. * - `{function=}` `destructiveButtonClicked` Called when the destructive button is clicked. * Return true to close the action sheet, or false to keep it opened. * - `{boolean=}` `cancelOnStateChange` Whether to cancel the actionSheet when navigating * to a new state. Default true. * - `{string}` `cssClass` The custom CSS class name. * * @returns {function} `hideSheet` A function which, when called, hides & cancels the action sheet. */ function actionSheet(opts) { var scope = $rootScope.$new(true); extend(scope, { cancel: noop, destructiveButtonClicked: noop, buttonClicked: noop, $deregisterBackButton: noop, buttons: [], cancelOnStateChange: true }, opts || {}); function textForIcon(text) { if (text && /icon/.test(text)) { scope.$actionSheetHasIcon = true; } } for (var x = 0; x < scope.buttons.length; x++) { textForIcon(scope.buttons[x].text); } textForIcon(scope.cancelText); textForIcon(scope.destructiveText); // Compile the template var element = scope.element = $compile('<ion-action-sheet ng-class="cssClass" buttons="buttons"></ion-action-sheet>')(scope); // Grab the sheet element for animation var sheetEl = jqLite(element[0].querySelector('.action-sheet-wrapper')); var stateChangeListenDone = scope.cancelOnStateChange ? $rootScope.$on('$stateChangeSuccess', function() { scope.cancel(); }) : noop; // removes the actionSheet from the screen scope.removeSheet = function(done) { if (scope.removed) return; scope.removed = true; sheetEl.removeClass('action-sheet-up'); $timeout(function() { // wait to remove this due to a 300ms delay native // click which would trigging whatever was underneath this $ionicBody.removeClass('action-sheet-open'); }, 400); scope.$deregisterBackButton(); stateChangeListenDone(); $animate.removeClass(element, 'active').then(function() { scope.$destroy(); element.remove(); // scope.cancel.$scope is defined near the bottom scope.cancel.$scope = sheetEl = null; (done || noop)(opts.buttons); }); }; scope.showSheet = function(done) { if (scope.removed) return; $ionicBody.append(element) .addClass('action-sheet-open'); $animate.addClass(element, 'active').then(function() { if (scope.removed) return; (done || noop)(); }); $timeout(function() { if (scope.removed) return; sheetEl.addClass('action-sheet-up'); }, 20, false); }; // registerBackButtonAction returns a callback to deregister the action scope.$deregisterBackButton = $ionicPlatform.registerBackButtonAction( function() { $timeout(scope.cancel); }, IONIC_BACK_PRIORITY.actionSheet ); // called when the user presses the cancel button scope.cancel = function() { // after the animation is out, call the cancel callback scope.removeSheet(opts.cancel); }; scope.buttonClicked = function(index) { // Check if the button click event returned true, which means // we can close the action sheet if (opts.buttonClicked(index, opts.buttons[index]) === true) { scope.removeSheet(); } }; scope.destructiveButtonClicked = function() { // Check if the destructive button click event returned true, which means // we can close the action sheet if (opts.destructiveButtonClicked() === true) { scope.removeSheet(); } }; scope.showSheet(); // Expose the scope on $ionicActionSheet's return value for the sake // of testing it. scope.cancel.$scope = scope; return scope.cancel; } }]);