release: v1.0.0-beta.10 "gadolinium-gator"

This commit is contained in:
Ionitron
2014-07-25 00:06:49 +00:00
parent 00ccd9c45c
commit 90f1e9fed0
11 changed files with 970 additions and 434 deletions

View File

@@ -2,7 +2,7 @@
* Copyright 2014 Drifty Co.
* http://drifty.com/
*
* Ionic, v1.0.0-beta.9
* Ionic, v1.0.0-beta.10
* A powerful HTML5 mobile app framework.
* http://ionicframework.com/
*
@@ -99,6 +99,9 @@ var IonicModule = angular.module('ionic', ['ngAnimate', 'ngSanitize', 'ui.router
* destructiveText: 'Delete',
* titleText: 'Modify your album',
* cancelText: 'Cancel',
* cancel: function() {
// add cancel code..
},
* buttonClicked: function(index) {
* return true;
* }
@@ -321,7 +324,7 @@ jqLite.prototype.removeClass = function(cssClasses) {
* ```js
* angular.module('mySuperApp', ['ionic'])
* .controller(function($scope, $ionicAnimation) {
* var anim = $ionicAnimate({
* var anim = $ionicAnimation({
* // A unique, reusable name
* name: 'popIn',
*
@@ -596,13 +599,11 @@ function($cacheFactory, $parse, $rootScope) {
return item;
},
getItem: function(hash) {
window.AMOUNT = window.AMOUNT || 0;
if ( (item = this.attachedItems[hash]) ) {
//do nothing, the item is good
} else if ( (item = this.backupItemsArray.pop()) ) {
reconnectScope(item.scope);
} else {
AMOUNT++;
item = this.createItem();
}
return item;
@@ -1171,6 +1172,7 @@ IonicModule
* @param {function(e)} callback The function to call when the gesture
* happens.
* @param {element} $element The angular element to listen for the event on.
* @returns {ionic.Gesture} The gesture object (use this to remove the gesture later on).
*/
on: function(eventType, cb, $element) {
return window.ionic.onGesture(eventType, cb, $element[0]);
@@ -1179,9 +1181,9 @@ IonicModule
* @ngdoc method
* @name $ionicGesture#off
* @description Remove an event listener for a gesture on an element. See {@link ionic.utility:ionic.EventController#offGesture}.
* @param {ionic.Gesture} gesture The gesture that should be removed.
* @param {string} eventType The gesture event to remove the listener for.
* @param {function(e)} callback The listener to remove.
* @param {element} $element The angular element that was listening for the event.
*/
off: function(gesture, eventType, cb) {
return window.ionic.offGesture(gesture, eventType, cb);
@@ -1191,7 +1193,9 @@ IonicModule
var LOADING_TPL =
'<div class="loading">' +
'<div class="loading-container">' +
'<div class="loading">' +
'</div>' +
'</div>';
var LOADING_HIDE_DEPRECATED = '$ionicLoading instance.hide() has been deprecated. Use $ionicLoading.hide().';
@@ -1221,8 +1225,32 @@ var LOADING_SET_DEPRECATED = '$ionicLoading instance.setContent() has been depre
* });
* ```
*/
/**
* @ngdoc object
* @name $ionicLoadingConfig
* @module ionic
* @description
* Set the default options to be passed to the {@link ionic.service:$ionicLoading} service.
*
* @usage
* ```js
* var app = angular.module('myApp', ['ionic'])
* app.constant('$ionicLoadingConfig', {
* template: 'Default Loading Template...'
* });
* app.controller('AppCtrl', function($scope, $ionicLoading) {
* $scope.showLoading = function() {
* $ionicLoading.show(); //options default to values in $ionicLoadingConfig
* };
* });
* ```
*/
IonicModule
.constant('$ionicLoadingConfig', {
template: '<i class="ion-loading-d"></i>'
})
.factory('$ionicLoading', [
'$ionicLoadingConfig',
'$document',
'$ionicTemplateLoader',
'$ionicBackdrop',
@@ -1231,7 +1259,7 @@ IonicModule
'$log',
'$compile',
'$ionicPlatform',
function($document, $ionicTemplateLoader, $ionicBackdrop, $timeout, $q, $log, $compile, $ionicPlatform) {
function($ionicLoadingConfig, $document, $ionicTemplateLoader, $ionicBackdrop, $timeout, $q, $log, $compile, $ionicPlatform) {
var loaderInstance;
//default values
@@ -1300,17 +1328,17 @@ function($document, $ionicTemplateLoader, $ionicBackdrop, $timeout, $q, $log, $c
templatePromise.then(function(html) {
if (html) {
self.element.html(html);
$compile(self.element.contents())(self.scope);
var loading = self.element.children();
loading.html(html);
$compile(loading.contents())(self.scope);
}
//Don't show until template changes
if (self.isShown) {
self.element.addClass('visible');
ionic.DomUtil.centerElementByMarginTwice(self.element[0]);
ionic.requestAnimationFrame(function() {
self.isShown && self.element.addClass('active');
ionic.DomUtil.centerElementByMarginTwice(self.element[0]);
$document[0].body.classList.add('loading-active');
});
}
});
@@ -1324,6 +1352,7 @@ function($document, $ionicTemplateLoader, $ionicBackdrop, $timeout, $q, $log, $c
$ionicBackdrop.getElement().removeClass('backdrop-loading');
}
self.element.removeClass('active');
$document[0].body.classList.remove('loading-active');
setTimeout(function() {
!self.isShown && self.element.removeClass('visible');
}, 200);
@@ -1339,7 +1368,7 @@ function($document, $ionicTemplateLoader, $ionicBackdrop, $timeout, $q, $log, $c
}
function showLoader(options) {
options || (options = {});
options = extend($ionicLoadingConfig || {}, options || {});
var delay = options.delay || options.showDelay || 0;
//If loading.show() was called previously, cancel it and show with our new options
@@ -1388,7 +1417,8 @@ function($document, $ionicTemplateLoader, $ionicBackdrop, $timeout, $q, $log, $c
*
* The Modal is a content pane that can go over the user's main view
* temporarily. Usually used for making a choice or editing an item.
* Note that you need to put the content of the modal inside a div with the class `modal`.
*
* Put the content of the modal inside of an `<ion-modal-view>` element.
*
* Note: a modal will broadcast 'modal.shown', 'modal.hidden', and 'modal.removed' events from its originating
* scope, passing in itself as an event argument. Both the modal.removed and modal.hidden events are
@@ -1397,14 +1427,14 @@ function($document, $ionicTemplateLoader, $ionicBackdrop, $timeout, $q, $log, $c
* @usage
* ```html
* <script id="my-modal.html" type="text/ng-template">
* <div class="modal">
* <ion-modal-view>
* <ion-header-bar>
* <h1 class="title">My Modal title</h1>
* </ion-header-bar>
* <ion-content>
* Hello!
* </ion-content>
* </div>
* </ion-modal-view>
* </script>
* ```
* ```js
@@ -1456,7 +1486,7 @@ function($rootScope, $document, $compile, $timeout, $ionicPlatform, $ionicTempla
* @description
* Instantiated by the {@link ionic.service:$ionicModal} service.
*
* Hint: Be sure to call [remove()](#remove) when you are done with each modal
* Be sure to call [remove()](#remove) when you are done with each modal
* to clean it up and avoid memory leaks.
*
* Note: a modal will broadcast 'modal.shown', 'modal.hidden', and 'modal.removed' events from its originating
@@ -1527,6 +1557,7 @@ function($rootScope, $document, $compile, $timeout, $ionicPlatform, $ionicTempla
$timeout(function(){
modalEl.addClass('ng-enter-active');
ionic.trigger('resize');
self.scope.$parent && self.scope.$parent.$broadcast('modal.shown', self);
self.el.classList.add('active');
}, 20);
@@ -2751,7 +2782,17 @@ IonicModule
* side menus.
* @returns {boolean} Whether the content can be dragged to open side menus.
*/
'canDragContent'
'canDragContent',
/**
* @ngdoc method
* @name $ionicSideMenuDelegate#edgeDragThreshold
* @param {boolean|number=} value Set whether the content drag can only start if it is below a certain threshold distance from the edge of the screen. Accepts three different values:
* - If a non-zero number is given, that many pixels is used as the maximum allowed distance from the edge that starts dragging the side menu.
* - If true is given, the default number of pixels (25) is used as the maximum allowed distance.
* - If false or 0 is given, the edge drag threshold is disabled, and dragging from anywhere on the content is allowed.
* @returns {boolean} Whether the drag can start only from within the edge of screen threshold.
*/
'edgeDragThreshold',
/**
* @ngdoc method
* @name $ionicSideMenuDelegate#$getByHandle
@@ -3093,7 +3134,7 @@ function($rootScope, $state, $location, $document, $animate, $ionicPlatform, $io
return false;
}
$ionicPlatform.registerBackButtonAction(
onHardwareBackButton,
onHardwareBackButton,
PLATFORM_BACK_BUTTON_PRIORITY_VIEW
);
@@ -3499,6 +3540,8 @@ function($rootScope, $state, $location, $window, $injector, $animate, $ionicNavV
}
});
return;
} else if(!doAnimation) {
document.body.classList.remove('disable-pointer-events');
}
// no animation
@@ -3935,7 +3978,6 @@ function($scope, scrollViewOptions, $timeout, $window, $$scrollValueCache, $loca
backListenDone();
if (self._rememberScrollId) {
$$scrollValueCache[self._rememberScrollId] = scrollView.getValues();
void 0;
}
});
@@ -3960,8 +4002,6 @@ function($scope, scrollViewOptions, $timeout, $window, $$scrollValueCache, $loca
self.rememberScrollPosition(viewId);
self.scrollToRememberedPosition();
void 0;
backListenDone = $rootScope.$on('$viewHistory.viewBack', function(e, fromViewId, toViewId) {
//When going back from this view, forget its saved scroll position
if (viewId === fromViewId) {
@@ -4019,12 +4059,19 @@ function($scope, scrollViewOptions, $timeout, $window, $$scrollValueCache, $loca
this.resize().then(function() {
var hash = $location.hash();
var elm = hash && $document[0].getElementById(hash);
if (hash && elm) {
var scroll = ionic.DomUtil.getPositionInParent(elm, self.$element);
scrollView.scrollTo(scroll.left, scroll.top, !!shouldAnimate);
} else {
if (!(hash && elm)) {
scrollView.scrollTo(0,0, !!shouldAnimate);
return;
}
var curElm = elm;
var scrollLeft = 0, scrollTop = 0, levelsClimbed = 0;
do {
if(curElm !== null)scrollLeft += curElm.offsetLeft;
if(curElm !== null)scrollTop += curElm.offsetTop;
curElm = curElm.offsetParent;
levelsClimbed++;
} while (curElm.attributes != self.element.attributes && curElm.offsetParent);
scrollView.scrollTo(scrollLeft, scrollTop, !!shouldAnimate);
});
};
@@ -4091,12 +4138,36 @@ function($scope, $attrs, $ionicSideMenuDelegate, $ionicPlatform) {
return $scope.dragContent;
};
this.edgeThreshold = 25;
this.edgeThresholdEnabled = false;
this.edgeDragThreshold = function(value) {
if (arguments.length) {
if (angular.isNumber(value) && value > 0) {
this.edgeThreshold = value;
this.edgeThresholdEnabled = true;
} else {
this.edgeThresholdEnabled = !!value;
}
}
return this.edgeThresholdEnabled;
};
this.isDraggableTarget = function(e) {
return $scope.dragContent &&
(!e.gesture.srcEvent.defaultPrevented &&
!e.target.tagName.match(/input|textarea|select|object|embed/i) &&
!e.target.isContentEditable &&
!(e.target.dataset ? e.target.dataset.preventScroll : e.target.getAttribute('data-prevent-default') == 'true'));
//Only restrict edge when sidemenu is closed and restriction is enabled
var shouldOnlyAllowEdgeDrag = self.edgeThresholdEnabled && !self.isOpen();
var startX = e.gesture.startEvent && e.gesture.startEvent.center &&
e.gesture.startEvent.center.pageX;
var dragIsWithinBounds = !shouldOnlyAllowEdgeDrag ||
startX <= self.edgeThreshold ||
startX >= self.content.offsetWidth - self.edgeThreshold;
return ($scope.dragContent || self.isOpen()) &&
dragIsWithinBounds &&
!e.gesture.srcEvent.defaultPrevented &&
!e.target.tagName.match(/input|textarea|select|object|embed/i) &&
!e.target.isContentEditable &&
!(e.target.dataset ? e.target.dataset.preventScroll : e.target.getAttribute('data-prevent-default') == 'true');
};
$scope.sideMenuContentTranslateX = 0;
@@ -4327,13 +4398,14 @@ IonicModule
replace: true,
require: '?ngModel',
transclude: true,
template: '<label class="item item-checkbox">' +
'<div class="checkbox checkbox-input-hidden disable-pointer-events">' +
'<input type="checkbox">' +
'<i class="checkbox-icon"></i>' +
'</div>' +
'<div class="item-content disable-pointer-events" ng-transclude></div>' +
'</label>',
template:
'<label class="item item-checkbox">' +
'<div class="checkbox checkbox-input-hidden disable-pointer-events">' +
'<input type="checkbox">' +
'<i class="checkbox-icon"></i>' +
'</div>' +
'<div class="item-content disable-pointer-events" ng-transclude></div>' +
'</label>',
compile: function(element, attr) {
var input = element.find('input');
forEach({
@@ -4375,19 +4447,19 @@ IonicModule
* Here are a few things to keep in mind while using collection-repeat:
*
* 1. The data supplied to collection-repeat must be an array.
* 2. You must explicitly tell the directive what size your items will be in the DOM, using directive attributes.
* 2. You must explicitly tell the directive what size your items will be in the DOM, using directive attributes.
* Pixel amounts or percentages are allowed (see below).
* 3. The elements rendered will be absolutely positioned: be sure to let your CSS work with
* this (see below).
* 4. Keep the HTML of your repeated elements as simple as possible.
* The more complicated your elements, the more likely it is that the on-demand compilation will cause
* The more complicated your elements, the more likely it is that the on-demand compilation will cause
* some jerkiness in the user's scrolling.
* 6. Each collection-repeat list will take up all of its parent scrollView's space.
* If you wish to have multiple lists on one page, put each list within its own
* {@link ionic.directive:ionScroll ionScroll} container.
* 7. You should not use the ng-show and ng-hide directives on your ion-content/ion-scroll elements that
* have a collection-repeat inside. ng-show and ng-hide apply the `display: none` css rule to the content's
* style, causing the scrollView to read the width and height of the content as 0. Resultingly,
* style, causing the scrollView to read the width and height of the content as 0. Resultingly,
* collection-repeat will render elements that have just been un-hidden incorrectly.
*
*
@@ -4445,7 +4517,7 @@ IonicModule
* </div>
* </ion-content>
* ```
* Percentage of total visible list dimensions. This example shows a 3 by 3 matrix that fits on the screen (3 rows and 3 colums). Note that dimensions are used in the creation of the element and therefore a measurement of the item cannnot be used as an input dimension.
* Percentage of total visible list dimensions. This example shows a 3 by 3 matrix that fits on the screen (3 rows and 3 colums). Note that dimensions are used in the creation of the element and therefore a measurement of the item cannnot be used as an input dimension.
* ```css
* .my-image-item img {
* height: 33%;
@@ -4493,6 +4565,11 @@ var COLLECTION_REPEAT_ATTR_WIDTH_ERROR = "collection-repeat expected attribute c
var COLLECTION_REPEAT_ATTR_REPEAT_ERROR = "collection-repeat expected expression in form of '_item_ in _collection_[ track by _id_]' but got '%'";
IonicModule
.directive({
ngSrc: collectionRepeatSrcDirective('ngSrc', 'src'),
ngSrcset: collectionRepeatSrcDirective('ngSrcset', 'srcset'),
ngHref: collectionRepeatSrcDirective('ngHref', 'href')
})
.directive('collectionRepeat', [
'$collectionRepeatManager',
'$collectionDataSource',
@@ -4504,6 +4581,7 @@ function($collectionRepeatManager, $collectionDataSource, $parse) {
terminal: true,
$$tlb: true,
require: '^$ionicScroll',
controller: [function(){}],
link: function($scope, $element, $attr, scrollCtrl, $transclude) {
var scrollView = scrollCtrl.scrollView;
if (scrollView.options.scrollingX && scrollView.options.scrollingY) {
@@ -4587,6 +4665,31 @@ function($collectionRepeatManager, $collectionDataSource, $parse) {
};
}]);
// Fix for #1674
// Problem: if an ngSrc or ngHref expression evaluates to a falsy value, it will
// not erase the previous truthy value of the href.
// In collectionRepeat, we re-use elements from before. So if the ngHref expression
// evaluates to truthy for item 1 and then falsy for item 2, if an element changes
// from representing item 1 to representing item 2, item 2 will still have
// item 1's href value.
// Solution: erase the href or src attribute if ngHref/ngSrc are falsy.
function collectionRepeatSrcDirective(ngAttrName, attrName) {
return [function() {
return {
priority: '99', // it needs to run after the attributes are interpolated
require: '^?collectionRepeat',
link: function(scope, element, attr, collectionRepeatCtrl) {
if (!collectionRepeatCtrl) return;
attr.$observe(ngAttrName, function(value) {
if (!value) {
element.removeAttr(attrName);
}
});
}
};
}];
}
/**
* @ngdoc directive
* @name ionContent
@@ -4625,6 +4728,8 @@ function($collectionRepeatManager, $collectionDataSource, $parse) {
* of the content. Defaults to true on iOS, false on Android.
* @param {expression=} on-scroll Expression to evaluate when the content is scrolled.
* @param {expression=} on-scroll-complete Expression to evaluate when a scroll action completes.
* @param {boolean=} has-bouncing Whether to allow scrolling to bounce past the edges
* of the content. Defaults to true on iOS, false on Android.
*/
IonicModule
.directive('ionContent', [
@@ -4725,13 +4830,11 @@ function($timeout, $controller, $ionicBind) {
};
}]);
var GESTURE_DIRECTIVES = 'onHold onTap onTouch onRelease onDrag onDragUp onDragRight onDragDown onDragLeft onSwipe onSwipeUp onSwipeRight onSwipeDown onSwipeLeft'.split(' ');
forEach(
'onHold onTap onTouch onRelease onDrag onDragUp onDragRight onDragDown onDragLeft onSwipe onSwipeUp onSwipeRight onSwipeBottom onSwipeLeft'.split(' '),
function(name) {
IonicModule.directive(name, gestureDirective(name));
}
);
GESTURE_DIRECTIVES.forEach(function(name) {
IonicModule.directive(name, gestureDirective(name));
});
/**
@@ -5006,11 +5109,12 @@ IonicModule
* Note: If you use ionHeaderBar in combination with ng-if, the surrounding content
* will not align correctly. This will be fixed soon.
*
* @param {string=} align-title Where to align the title.
* @param {string=} align-title Where to align the title.
* Available: 'left', 'right', or 'center'. Defaults to 'center'.
* @param {boolean=} no-tap-scroll By default, the header bar will scroll the
* content to the top when tapped. Set no-tap-scroll to true to disable this
* behavior.
* Avaialble: 'left', 'right', or 'center'. Defaults to 'center'.
* Available: true or false. Defaults to false.
*
* @usage
* ```html
@@ -5046,7 +5150,7 @@ IonicModule
* will not align correctly. This will be fixed soon.
*
* @param {string=} align-title Where to align the title.
* Avaialble: 'left', 'right', or 'center'. Defaults to 'center'.
* Available: 'left', 'right', or 'center'. Defaults to 'center'.
*
* @usage
* ```html
@@ -5368,7 +5472,7 @@ function($animate, $compile) {
var ITEM_TPL_DELETE_BUTTON =
'<div class="item-left-edit item-delete ng-hide">' +
'<div class="item-left-edit item-delete enable-pointer-events">' +
'</div>';
/**
* @ngdoc directive
@@ -5402,7 +5506,7 @@ IonicModule
.directive('ionDeleteButton', ['$animate', function($animate) {
return {
restrict: 'E',
require: ['^ionItem', '^ionList'],
require: ['^ionItem', '^?ionList'],
//Run before anything else, so we can move it before other directives process
//its location (eg ngIf relies on the location of the directive in the dom)
priority: Number.MAX_VALUE,
@@ -5417,8 +5521,8 @@ IonicModule
container.append($element);
itemCtrl.$element.append(container).addClass('item-left-editable');
if (listCtrl.showDelete()) {
$animate.removeClass(container, 'ng-hide');
if (listCtrl && listCtrl.showDelete()) {
container.addClass('visible active');
}
};
}
@@ -5517,7 +5621,7 @@ IonicModule
}]);
var ITEM_TPL_REORDER_BUTTON =
'<div data-prevent-scroll="true" class="item-right-edit item-reorder ng-hide">' +
'<div data-prevent-scroll="true" class="item-right-edit item-reorder enable-pointer-events">' +
'</div>';
/**
@@ -5532,17 +5636,18 @@ var ITEM_TPL_REORDER_BUTTON =
*
* Can be dragged to reorder items in the list. Takes any ionicon class.
*
* When an item reorder is complete, the `on-reorder` callback given in the attribute is called
* (see below).
* Note: Reordering works best when used with `ng-repeat`. Be sure that all `ion-item` children of an `ion-list` are part of the same `ng-repeat` expression.
*
* See {@link ionic.directive:ionList} for a complete example.
* When an item reorder is complete, the expression given in the `on-reorder` attribute is called. The `on-reorder` expression is given two locals that can be used: `$fromIndex` and `$toIndex`. See below for an example.
*
* Look at {@link ionic.directive:ionList} for more examples.
*
* @usage
*
* ```html
* <ion-list ng-controller="MyCtrl">
* <ion-item ng-repeat="item in items">
* Item {{$index}}
* Item {{item}}
* <ion-reorder-button class="ion-navicon"
* on-reorder="moveItem(item, $fromIndex, $toIndex)">
* </ion-reorder>
@@ -5564,10 +5669,10 @@ var ITEM_TPL_REORDER_BUTTON =
* Parameters given: $fromIndex, $toIndex.
*/
IonicModule
.directive('ionReorderButton', ['$animate', function($animate) {
.directive('ionReorderButton', ['$animate', '$parse', function($animate, $parse) {
return {
restrict: 'E',
require: ['^ionItem', '^ionList'],
require: ['^ionItem', '^?ionList'],
priority: Number.MAX_VALUE,
compile: function($element, $attr) {
$attr.$set('class', ($attr['class'] || '') + ' button icon button-icon', true);
@@ -5575,8 +5680,10 @@ IonicModule
return function($scope, $element, $attr, ctrls) {
var itemCtrl = ctrls[0];
var listCtrl = ctrls[1];
var onReorderFn = $parse($attr.onReorder);
$scope.$onReorder = function(oldIndex, newIndex) {
$scope.$eval($attr.onReorder, {
onReorderFn($scope, {
$fromIndex: oldIndex,
$toIndex: newIndex
});
@@ -5586,8 +5693,8 @@ IonicModule
container.append($element);
itemCtrl.$element.append(container).addClass('item-right-editable');
if (listCtrl.showReorder()) {
$animate.removeClass(container, 'ng-hide');
if (listCtrl && listCtrl.showReorder()) {
container.addClass('visible active');
}
};
}
@@ -5783,7 +5890,7 @@ function($animate, $timeout) {
//Make sure onReorder is called in apply cycle,
//but also make sure it has no conflicts by doing
//$evalAsync
itemScope.$evalAsync(function() {
$timeout(function() {
itemScope.$onReorder(oldIndex, newIndex);
});
}
@@ -5793,18 +5900,17 @@ function($animate, $timeout) {
}
});
if (angular.isDefined($attr.canSwipe)) {
if (isDefined($attr.canSwipe)) {
$scope.$watch('!!(' + $attr.canSwipe + ')', function(value) {
listCtrl.canSwipeItems(value);
});
}
if (angular.isDefined($attr.showDelete)) {
if (isDefined($attr.showDelete)) {
$scope.$watch('!!(' + $attr.showDelete + ')', function(value) {
listCtrl.showDelete(value);
});
}
if (angular.isDefined($attr.showReorder)) {
if (isDefined($attr.showReorder)) {
$scope.$watch('!!(' + $attr.showReorder + ')', function(value) {
listCtrl.showReorder(value);
});
@@ -5820,9 +5926,12 @@ function($animate, $timeout) {
listCtrl.canSwipeItems(!isShown);
$element.children().toggleClass('list-left-editing', isShown);
toggleNgHide('.item-delete.item-left-edit', isShown);
toggleTapDisabled('.item-content', isShown);
$element.toggleClass('disable-pointer-events', isShown);
var deleteButton = jqLite($element[0].getElementsByClassName('item-delete'));
setButtonShown(deleteButton, listCtrl.showDelete);
});
$scope.$watch(function() {
return listCtrl.showReorder();
}, function(isShown, wasShown) {
@@ -5833,27 +5942,18 @@ function($animate, $timeout) {
listCtrl.canSwipeItems(!isShown);
$element.children().toggleClass('list-right-editing', isShown);
toggleNgHide('.item-reorder.item-right-edit', isShown);
toggleTapDisabled('.item-content', isShown);
$element.toggleClass('disable-pointer-events', isShown);
var reorderButton = jqLite($element[0].getElementsByClassName('item-reorder'));
setButtonShown(reorderButton, listCtrl.showReorder);
});
function toggleNgHide(selector, shouldShow) {
forEach($element[0].querySelectorAll(selector), function(node) {
if (shouldShow) {
$animate.removeClass(jqLite(node), 'ng-hide');
} else {
$animate.addClass(jqLite(node), 'ng-hide');
}
function setButtonShown(el, shown) {
shown() && el.addClass('visible') || el.removeClass('active');
ionic.requestAnimationFrame(function() {
shown() && el.addClass('active') || el.removeClass('invisible');
});
}
function toggleTapDisabled(selector, shouldDisable) {
var el = jqLite($element[0].querySelectorAll(selector));
if (shouldDisable) {
el.attr('data-tap-disabled', 'true');
} else {
el.removeAttr('data-tap-disabled');
}
}
}
};
@@ -5942,12 +6042,23 @@ IonicModule
restrict: 'E',
transclude: true,
replace: true,
controller: [function(){}],
template: '<div class="modal-backdrop">' +
'<div class="modal-wrapper" ng-transclude></div>' +
'</div>'
};
}]);
IonicModule
.directive('ionModalView', function() {
return {
restrict: 'E',
compile: function(element, attr) {
element.addClass('modal');
}
};
});
/**
* @ngdoc directive
* @name ionNavBackButton
@@ -5979,7 +6090,7 @@ IonicModule
* ```html
* <ion-nav-bar ng-controller="MyCtrl">
* <ion-nav-back-button class="button-clear"
* ng-click="canGoBack && goBack()">
* ng-click="doSomethingCool()">
* <i class="ion-arrow-left-c"></i> Back
* </ion-nav-back-button>
* </ion-nav-bar>
@@ -6083,8 +6194,9 @@ IonicModule.constant('$ionicNavBarConfig', {
* We can add buttons depending on the currently visible view using
* {@link ionic.directive:ionNavButtons}.
*
* Assign an [animation class](/docs/components#animations) to the element to
* enable animated changing of titles (recommended: 'nav-title-slide-ios7')
* Add an [animation class](/docs/components#animations) to the element via the
* `animation` attribute to enable animated changing of titles
* (recommended: 'nav-title-slide-ios7').
*
* Note that the ion-nav-bar element will only work correctly if your content has an
* ionView around it.
@@ -6094,7 +6206,7 @@ IonicModule.constant('$ionicNavBarConfig', {
* ```html
* <body ng-app="starter">
* <!-- The nav bar that will be updated as we navigate -->
* <ion-nav-bar class="bar-positive nav-title-slide-ios7">
* <ion-nav-bar class="bar-positive" animation="nav-title-slide-ios7">
* </ion-nav-bar>
*
* <!-- where the initial view template will be rendered -->
@@ -6156,7 +6268,7 @@ function($ionicViewService, $rootScope, $animate, $compile, $ionicNavBarConfig)
compile: function(tElement, tAttrs) {
//We cannot transclude here because it breaks element.data() inheritance on compile
tElement
.addClass('bar bar-header nav-bar ' + $ionicNavBarConfig.transition)
.addClass('bar bar-header nav-bar')
.append(
'<div class="buttons left-buttons"> ' +
'</div>' +
@@ -6165,6 +6277,12 @@ function($ionicViewService, $rootScope, $animate, $compile, $ionicNavBarConfig)
'</div>'
);
if (isDefined(tAttrs.animation)) {
tElement.addClass(tAttrs.animation);
} else {
tElement.addClass($ionicNavBarConfig.transition);
}
return { pre: prelink };
function prelink($scope, $element, $attr, navBarCtrl) {
navBarCtrl._headerBarView = new ionic.views.HeaderBar({
@@ -6947,6 +7065,7 @@ IonicModule
* @usage
* ```html
* <ion-side-menu-content
* edge-drag-threshold="true"
* drag-content="true">
* </ion-side-menu-content>
* ```
@@ -6954,6 +7073,10 @@ IonicModule
* {@link ionic.directive:ionSideMenus} documentation.
*
* @param {boolean=} drag-content Whether the content can be dragged. Default true.
* @param {boolean|number=} edge-drag-threshold Whether the content drag can only start if it is below a certain threshold distance from the edge of the screen. Default false. Accepts three types of values:
* - If a non-zero number is given, that many pixels is used as the maximum allowed distance from the edge that starts dragging the side menu.
* - If true is given, the default number of pixels (25) is used as the maximum allowed distance.
* - If false or 0 is given, the edge drag threshold is disabled, and dragging from anywhere on the content is allowed.
*
*/
IonicModule
@@ -6972,7 +7095,7 @@ function($timeout, $ionicGesture) {
$element.addClass('menu-content pane');
if (angular.isDefined(attr.dragContent)) {
if (isDefined(attr.dragContent)) {
$scope.$watch(attr.dragContent, function(value) {
sideMenuCtrl.canDragContent(value);
});
@@ -6980,6 +7103,12 @@ function($timeout, $ionicGesture) {
sideMenuCtrl.canDragContent(true);
}
if (isDefined(attr.edgeDragThreshold)) {
$scope.$watch(attr.edgeDragThreshold, function(value) {
sideMenuCtrl.edgeDragThreshold(value);
});
}
var defaultPrevented = false;
var isDragging = false;
@@ -7022,6 +7151,7 @@ function($timeout, $ionicGesture) {
var releaseGesture = $ionicGesture.on('release', dragReleaseFn, $element);
sideMenuCtrl.setContent({
element: element[0],
onDrag: function(e) {},
endDrag: function(e) {},
getTranslateX: function() {
@@ -7150,7 +7280,8 @@ IonicModule
*
* @param {string=} delegate-handle The handle used to identify this slideBox
* with {@link ionic.service:$ionicSlideBoxDelegate}.
* @param {boolean=} does-continue Whether the slide box should automatically slide.
* @param {boolean=} does-continue Whether the slide box should loop.
* @param {boolean=} auto-play Whether the slide box should automatically slide. Default true if does-continue is true.
* @param {number=} slide-interval How many milliseconds to wait to change slides (if does-continue is true). Defaults to 4000.
* @param {boolean=} show-pager Whether a pager should be shown for this slide box.
* @param {expression=} pager-click Expression to call when a pager is clicked (if show-pager is true). Is passed the 'index' variable.
@@ -7168,6 +7299,7 @@ function($timeout, $compile, $ionicSlideBoxDelegate) {
replace: true,
transclude: true,
scope: {
autoPlay: '=',
doesContinue: '@',
slideInterval: '@',
showPager: '@',
@@ -7180,7 +7312,8 @@ function($timeout, $compile, $ionicSlideBoxDelegate) {
var _this = this;
var continuous = $scope.$eval($scope.doesContinue) === true;
var slideInterval = continuous ? $scope.$eval($scope.slideInterval) || 4000 : 0;
var shouldAutoPlay = isDefined($attrs.autoPlay) ? !!$scope.autoPlay : false;
var slideInterval = shouldAutoPlay ? $scope.$eval($scope.slideInterval) || 4000 : 0;
var slider = new ionic.views.Slider({
el: $element[0],
@@ -7375,6 +7508,7 @@ function($rootScope, $animate, $ionicBind, $compile) {
attrStr('icon-off', attr.iconOff) +
attrStr('badge', attr.badge) +
attrStr('badge-style', attr.badgeStyle) +
attrStr('hidden', attr.hidden) +
attrStr('class', attr['class']) +
'></ion-tab-nav>';
@@ -7453,7 +7587,7 @@ IonicModule
replace: true,
require: ['^ionTabs', '^ionTab'],
template:
'<a ng-class="{\'tab-item-active\': isTabActive(), \'has-badge\':badge}" ' +
'<a ng-class="{\'tab-item-active\': isTabActive(), \'has-badge\':badge, \'tab-hidden\':isHidden()}" ' +
' class="tab-item">' +
'<span class="badge {{badgeStyle}}" ng-if="badge">{{badge}}</span>' +
'<i class="icon {{getIconOn()}}" ng-if="getIconOn() && isTabActive()"></i>' +
@@ -7466,6 +7600,7 @@ IonicModule
iconOn: '@',
iconOff: '@',
badge: '=',
hidden: '@',
badgeStyle: '@',
'class': '@'
},
@@ -7489,6 +7624,11 @@ IonicModule
});
}
$scope.isHidden = function() {
if($attrs.hidden === 'true' || $attrs.hidden === true)return true;
return false;
};
$scope.getIconOn = function() {
return $scope.iconOn || $scope.icon;
};
@@ -7636,33 +7776,34 @@ function($ionicGesture, $timeout) {
restrict: 'E',
replace: true,
require: '?ngModel',
scope: {
ngModel: '=?',
ngValue: '=?',
ngChecked: '=?',
ngChange: '&',
ngDisabled: '=?'
},
transclude: true,
template: '<div class="item item-toggle">' +
'<div ng-transclude></div>' +
'<label class="toggle">' +
'<input type="checkbox" ng-model="ngModel" ng-value="ngValue" ng-change="ngChange()" ng-disabled="ngDisabled">' +
'<div class="track">' +
'<div class="handle"></div>' +
'</div>' +
'</label>' +
'</div>',
template:
'<div class="item item-toggle">' +
'<div ng-transclude></div>' +
'<label class="toggle">' +
'<input type="checkbox">' +
'<div class="track">' +
'<div class="handle"></div>' +
'</div>' +
'</label>' +
'</div>',
compile: function(element, attr) {
var input = element.find('input');
if(attr.name) input.attr('name', attr.name);
if(attr.ngChecked) input.attr('ng-checked', 'ngChecked');
if(attr.ngTrueValue) input.attr('ng-true-value', attr.ngTrueValue);
if(attr.ngFalseValue) input.attr('ng-false-value', attr.ngFalseValue);
if(attr.toggleClass) {
element[0].getElementsByTagName('label')[0].classList.add(attr.toggleClass);
}
forEach({
'name': attr.name,
'ng-value': attr.ngValue,
'ng-model': attr.ngModel,
'ng-checked': attr.ngChecked,
'ng-disabled': attr.ngDisabled,
'ng-true-value': attr.ngTrueValue,
'ng-false-value': attr.ngFalseValue,
'ng-change': attr.ngChange
}, function(value, name) {
if (isDefined(value)) {
input.attr(name, value);
}
});
return function($scope, $element, $attr) {
var el, checkbox, track, handle;
@@ -7735,13 +7876,17 @@ IonicModule
return {
restrict: 'EA',
priority: 1000,
require: '^?ionNavBar',
require: ['^?ionNavBar', '^?ionModal'],
compile: function(tElement, tAttrs, transclude) {
tElement.addClass('pane');
tElement[0].removeAttribute('title');
return function link($scope, $element, $attr, navBarCtrl) {
if (!navBarCtrl) {
return function link($scope, $element, $attr, ctrls) {
var navBarCtrl = ctrls[0];
var modalCtrl = ctrls[1];
//Don't use the ionView if we're inside a modal or there's no navbar
if (!navBarCtrl || modalCtrl) {
return;
}