mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2026-03-13 10:22:08 +08:00
206 lines
6.5 KiB
JavaScript
206 lines
6.5 KiB
JavaScript
/**
|
|
* @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.
|
|
*
|
|
* 
|
|
*
|
|
* @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',
|
|
function($rootScope, $compile, $animate, $timeout, $ionicTemplateLoader, $ionicPlatform, $ionicBody) {
|
|
|
|
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)();
|
|
});
|
|
};
|
|
|
|
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);
|
|
},
|
|
PLATFORM_BACK_BUTTON_PRIORITY_ACTION_SHEET
|
|
);
|
|
|
|
// 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;
|
|
}
|
|
}]);
|