mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2026-03-13 10:22:08 +08:00
refactor(): reorganize source files
This commit is contained in:
115
js/angular/controller/listController.js
vendored
Normal file
115
js/angular/controller/listController.js
vendored
Normal file
@@ -0,0 +1,115 @@
|
||||
|
||||
/**
|
||||
* @ngdoc service
|
||||
* @name $ionicListDelegate
|
||||
* @module ionic
|
||||
*
|
||||
* @description
|
||||
* Delegate for controlling the {@link ionic.directive:ionList} directive.
|
||||
*
|
||||
* Methods called directly on the $ionicListDelegate service will control all lists.
|
||||
* Use the {@link ionic.service:$ionicListDelegate#$getByHandle $getByHandle}
|
||||
* method to control specific ionList instances.
|
||||
*
|
||||
* @usage
|
||||
*
|
||||
* ````html
|
||||
* <ion-content ng-controller="MyCtrl">
|
||||
* <button class="button" ng-click="showDeleteButtons()"></button>
|
||||
* <ion-list>
|
||||
* <ion-item ng-repeat="i in items">>
|
||||
* {% raw %}Hello, {{i}}!{% endraw %}
|
||||
* <ion-delete-button class="ion-minus-circled"></ion-delete-button>
|
||||
* </ion-item>
|
||||
* </ion-list>
|
||||
* </ion-content>
|
||||
* ```
|
||||
* ```js
|
||||
* function MyCtrl($scope, $ionicListDelegate) {
|
||||
* $scope.showDeleteButtons = function() {
|
||||
* $ionicListDelegate.showDelete(true);
|
||||
* };
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
IonicModule
|
||||
.service('$ionicListDelegate', delegateService([
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name $ionicListDelegate#showReorder
|
||||
* @param {boolean=} showReorder Set whether or not this list is showing its reorder buttons.
|
||||
* @returns {boolean} Whether the reorder buttons are shown.
|
||||
*/
|
||||
'showReorder',
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name $ionicListDelegate#showDelete
|
||||
* @param {boolean=} showReorder Set whether or not this list is showing its delete buttons.
|
||||
* @returns {boolean} Whether the delete buttons are shown.
|
||||
*/
|
||||
'showDelete',
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name $ionicListDelegate#canSwipeItems
|
||||
* @param {boolean=} showReorder Set whether or not this list is able to swipe to show
|
||||
* option buttons.
|
||||
* @returns {boolean} Whether the list is able to swipe to show option buttons.
|
||||
*/
|
||||
'canSwipeItems',
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name $ionicListDelegate#closeOptionButtons
|
||||
* @description Closes any option buttons on the list that are swiped open.
|
||||
*/
|
||||
'closeOptionButtons',
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name $ionicListDelegate#$getByHandle
|
||||
* @param {string} handle
|
||||
* @returns `delegateInstance` A delegate instance that controls only the
|
||||
* {@link ionic.directive:ionList} directives with `delegate-handle` matching
|
||||
* the given handle.
|
||||
*
|
||||
* Example: `$ionicListDelegate.$getByHandle('my-handle').showReorder(true);`
|
||||
*/
|
||||
]))
|
||||
|
||||
.controller('$ionicList', [
|
||||
'$scope',
|
||||
'$attrs',
|
||||
'$parse',
|
||||
'$ionicListDelegate',
|
||||
function($scope, $attrs, $parse, $ionicListDelegate) {
|
||||
|
||||
var isSwipeable = true;
|
||||
var isReorderShown = false;
|
||||
var isDeleteShown = false;
|
||||
|
||||
var deregisterInstance = $ionicListDelegate._registerInstance(this, $attrs.delegateHandle);
|
||||
$scope.$on('$destroy', deregisterInstance);
|
||||
|
||||
this.showReorder = function(show) {
|
||||
if (arguments.length) {
|
||||
isReorderShown = !!show;
|
||||
}
|
||||
return isReorderShown;
|
||||
};
|
||||
|
||||
this.showDelete = function(show) {
|
||||
if (arguments.length) {
|
||||
isDeleteShown = !!show;
|
||||
}
|
||||
return isDeleteShown;
|
||||
};
|
||||
|
||||
this.canSwipeItems = function(can) {
|
||||
if (arguments.length) {
|
||||
isSwipeable = !!can;
|
||||
}
|
||||
return isSwipeable;
|
||||
};
|
||||
|
||||
this.closeOptionButtons = function() {
|
||||
this.listView && this.listView.clearDragEffects();
|
||||
};
|
||||
}]);
|
||||
129
js/angular/controller/navBarController.js
vendored
Normal file
129
js/angular/controller/navBarController.js
vendored
Normal file
@@ -0,0 +1,129 @@
|
||||
IonicModule
|
||||
.controller('$ionicNavBar', [
|
||||
'$scope',
|
||||
'$element',
|
||||
'$attrs',
|
||||
'$ionicViewService',
|
||||
'$animate',
|
||||
'$compile',
|
||||
'$ionicNavBarDelegate',
|
||||
function($scope, $element, $attrs, $ionicViewService, $animate, $compile, $ionicNavBarDelegate) {
|
||||
//Let the parent know about our controller too so that children of
|
||||
//sibling content elements can know about us
|
||||
$element.parent().data('$ionNavBarController', this);
|
||||
|
||||
var deregisterInstance = $ionicNavBarDelegate._registerInstance(this, $attrs.delegateHandle);
|
||||
|
||||
$scope.$on('$destroy', deregisterInstance);
|
||||
|
||||
var self = this;
|
||||
|
||||
this.leftButtonsElement = angular.element(
|
||||
$element[0].querySelector('.buttons.left-buttons')
|
||||
);
|
||||
this.rightButtonsElement = angular.element(
|
||||
$element[0].querySelector('.buttons.right-buttons')
|
||||
);
|
||||
|
||||
this.back = function(e) {
|
||||
var backView = $ionicViewService.getBackView();
|
||||
backView && backView.go();
|
||||
e && (e.alreadyHandled = true);
|
||||
return false;
|
||||
};
|
||||
|
||||
this.align = function(direction) {
|
||||
this._headerBarView.align(direction);
|
||||
};
|
||||
|
||||
this.showBackButton = function(show) {
|
||||
if (arguments.length) {
|
||||
$scope.backButtonShown = !!show;
|
||||
}
|
||||
return !!($scope.hasBackButton && $scope.backButtonShown);
|
||||
};
|
||||
|
||||
this.showBar = function(show) {
|
||||
if (arguments.length) {
|
||||
$scope.isInvisible = !show;
|
||||
$scope.$parent.$hasHeader = !!show;
|
||||
}
|
||||
return !$scope.isInvisible;
|
||||
};
|
||||
|
||||
this.setTitle = function(title) {
|
||||
$scope.oldTitle = $scope.title;
|
||||
$scope.title = title || '';
|
||||
};
|
||||
|
||||
this.changeTitle = function(title, direction) {
|
||||
if ($scope.title === title) {
|
||||
return false;
|
||||
}
|
||||
this.setTitle(title);
|
||||
$scope.isReverse = direction == 'back';
|
||||
$scope.shouldAnimate = !!direction;
|
||||
|
||||
if (!$scope.shouldAnimate) {
|
||||
//We're done!
|
||||
this._headerBarView.align();
|
||||
} else {
|
||||
this._animateTitles();
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
this.getTitle = function() {
|
||||
return $scope.title || '';
|
||||
};
|
||||
|
||||
this.getPreviousTitle = function() {
|
||||
return $scope.oldTitle || '';
|
||||
};
|
||||
|
||||
/**
|
||||
* Exposed for testing
|
||||
*/
|
||||
this._animateTitles = function() {
|
||||
var oldTitleEl, newTitleEl, currentTitles;
|
||||
|
||||
//If we have any title right now
|
||||
//(or more than one, they could be transitioning on switch),
|
||||
//replace the first one with an oldTitle element
|
||||
currentTitles = $element[0].querySelectorAll('.title');
|
||||
if (currentTitles.length) {
|
||||
oldTitleEl = $compile('<h1 class="title" ng-bind-html="oldTitle"></h1>')($scope);
|
||||
angular.element(currentTitles[0]).replaceWith(oldTitleEl);
|
||||
}
|
||||
//Compile new title
|
||||
newTitleEl = $compile('<h1 class="title invisible" ng-bind-html="title"></h1>')($scope);
|
||||
|
||||
//Animate in on next frame
|
||||
ionic.requestAnimationFrame(function() {
|
||||
|
||||
oldTitleEl && $animate.leave(angular.element(oldTitleEl));
|
||||
|
||||
var insert = oldTitleEl && angular.element(oldTitleEl) || null;
|
||||
$animate.enter(newTitleEl, $element, insert, function() {
|
||||
self._headerBarView.align();
|
||||
});
|
||||
|
||||
//Cleanup any old titles leftover (besides the one we already did replaceWith on)
|
||||
angular.forEach(currentTitles, function(el) {
|
||||
if (el && el.parentNode) {
|
||||
//Use .remove() to cleanup things like .data()
|
||||
angular.element(el).remove();
|
||||
}
|
||||
});
|
||||
|
||||
//$apply so bindings fire
|
||||
$scope.$digest();
|
||||
|
||||
//Stop flicker of new title on ios7
|
||||
ionic.requestAnimationFrame(function() {
|
||||
newTitleEl[0].classList.remove('invisible');
|
||||
});
|
||||
});
|
||||
};
|
||||
}])
|
||||
|
||||
186
js/angular/controller/scrollController.js
vendored
Normal file
186
js/angular/controller/scrollController.js
vendored
Normal file
@@ -0,0 +1,186 @@
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
IonicModule
|
||||
|
||||
.factory('$$scrollValueCache', function() {
|
||||
return {};
|
||||
})
|
||||
|
||||
.controller('$ionicScroll', [
|
||||
'$scope',
|
||||
'scrollViewOptions',
|
||||
'$timeout',
|
||||
'$window',
|
||||
'$$scrollValueCache',
|
||||
'$location',
|
||||
'$rootScope',
|
||||
'$document',
|
||||
'$ionicScrollDelegate',
|
||||
function($scope, scrollViewOptions, $timeout, $window, $$scrollValueCache, $location, $rootScope, $document, $ionicScrollDelegate) {
|
||||
|
||||
var self = this;
|
||||
|
||||
this._scrollViewOptions = scrollViewOptions; //for testing
|
||||
|
||||
var element = this.element = scrollViewOptions.el;
|
||||
var $element = this.$element = angular.element(element);
|
||||
var scrollView = this.scrollView = new ionic.views.Scroll(scrollViewOptions);
|
||||
|
||||
//Attach self to element as a controller so other directives can require this controller
|
||||
//through `require: '$ionicScroll'
|
||||
//Also attach to parent so that sibling elements can require this
|
||||
($element.parent().length ? $element.parent() : $element)
|
||||
.data('$$ionicScrollController', this);
|
||||
|
||||
var deregisterInstance = $ionicScrollDelegate._registerInstance(
|
||||
this, scrollViewOptions.delegateHandle
|
||||
);
|
||||
|
||||
if (!angular.isDefined(scrollViewOptions.bouncing)) {
|
||||
ionic.Platform.ready(function() {
|
||||
scrollView.options.bouncing = !ionic.Platform.isAndroid();
|
||||
});
|
||||
}
|
||||
|
||||
var resize = angular.bind(scrollView, scrollView.resize);
|
||||
ionic.on('resize', resize, $window);
|
||||
|
||||
// set by rootScope listener if needed
|
||||
var backListenDone = angular.noop;
|
||||
|
||||
$scope.$on('$destroy', function() {
|
||||
deregisterInstance();
|
||||
ionic.off('resize', resize, $window);
|
||||
$window.removeEventListener('resize', resize);
|
||||
backListenDone();
|
||||
if (self._rememberScrollId) {
|
||||
$$scrollValueCache[self._rememberScrollId] = scrollView.getValues();
|
||||
}
|
||||
});
|
||||
|
||||
$element.on('scroll', function(e) {
|
||||
var detail = (e.originalEvent || e).detail || {};
|
||||
$scope.$onScroll && $scope.$onScroll({
|
||||
event: e,
|
||||
scrollTop: detail.scrollTop || 0,
|
||||
scrollLeft: detail.scrollLeft || 0
|
||||
});
|
||||
});
|
||||
|
||||
$scope.$on('$viewContentLoaded', function(e, historyData) {
|
||||
//only the top-most scroll area under a view should remember that view's
|
||||
//scroll position
|
||||
if (e.defaultPrevented) { return; }
|
||||
e.preventDefault();
|
||||
|
||||
var viewId = historyData && historyData.viewId;
|
||||
if (viewId) {
|
||||
self.rememberScrollPosition(viewId);
|
||||
self.scrollToRememberedPosition();
|
||||
|
||||
backListenDone = $rootScope.$on('$viewHistory.viewBack', function(e, fromViewId, toViewId) {
|
||||
//When going back from this view, forget its saved scroll position
|
||||
if (viewId === fromViewId) {
|
||||
self.forgetScrollPosition();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
$timeout(function() {
|
||||
scrollView.run();
|
||||
});
|
||||
|
||||
this._rememberScrollId = null;
|
||||
|
||||
this.getScrollView = function() {
|
||||
return this.scrollView;
|
||||
};
|
||||
|
||||
this.getScrollPosition = function() {
|
||||
return this.scrollView.getValues();
|
||||
};
|
||||
|
||||
this.resize = function() {
|
||||
return $timeout(resize);
|
||||
};
|
||||
|
||||
this.scrollTop = function(shouldAnimate) {
|
||||
this.resize().then(function() {
|
||||
scrollView.scrollTo(0, 0, !!shouldAnimate);
|
||||
});
|
||||
};
|
||||
|
||||
this.scrollBottom = function(shouldAnimate) {
|
||||
this.resize().then(function() {
|
||||
var max = scrollView.getScrollMax();
|
||||
scrollView.scrollTo(max.left, max.top, !!shouldAnimate);
|
||||
});
|
||||
};
|
||||
|
||||
this.scrollTo = function(left, top, shouldAnimate) {
|
||||
this.resize().then(function() {
|
||||
scrollView.scrollTo(left, top, !!shouldAnimate);
|
||||
});
|
||||
};
|
||||
|
||||
this.scrollBy = function(left, top, shouldAnimate) {
|
||||
this.resize().then(function() {
|
||||
scrollView.scrollBy(left, top, !!shouldAnimate);
|
||||
});
|
||||
};
|
||||
|
||||
this.anchorScroll = function(shouldAnimate) {
|
||||
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 {
|
||||
scrollView.scrollTo(0,0, !!shouldAnimate);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
this.rememberScrollPosition = function(id) {
|
||||
if (!id) {
|
||||
throw new Error("Must supply an id to remember the scroll by!");
|
||||
}
|
||||
this._rememberScrollId = id;
|
||||
};
|
||||
this.forgetScrollPosition = function() {
|
||||
delete $$scrollValueCache[this._rememberScrollId];
|
||||
this._rememberScrollId = null;
|
||||
};
|
||||
this.scrollToRememberedPosition = function(shouldAnimate) {
|
||||
var values = $$scrollValueCache[this._rememberScrollId];
|
||||
if (values) {
|
||||
this.resize().then(function() {
|
||||
scrollView.scrollTo(+values.left, +values.top, shouldAnimate);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
this._setRefresher = function(refresherScope, refresherElement) {
|
||||
var refresher = this.refresher = refresherElement;
|
||||
var refresherHeight = self.refresher.clientHeight || 0;
|
||||
scrollView.activatePullToRefresh(refresherHeight, function() {
|
||||
refresher.classList.add('active');
|
||||
refresherScope.$onPulling();
|
||||
}, function() {
|
||||
refresher.classList.remove('refreshing');
|
||||
refresher.classList.remove('active');
|
||||
}, function() {
|
||||
refresher.classList.add('refreshing');
|
||||
refresherScope.$onRefresh();
|
||||
});
|
||||
};
|
||||
}]);
|
||||
|
||||
35
js/angular/controller/sideMenuController.js
vendored
Normal file
35
js/angular/controller/sideMenuController.js
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
IonicModule
|
||||
.controller('$ionicSideMenus', [
|
||||
'$scope',
|
||||
'$attrs',
|
||||
'$ionicSideMenuDelegate',
|
||||
function($scope, $attrs, $ionicSideMenuDelegate) {
|
||||
angular.extend(this, ionic.controllers.SideMenuController.prototype);
|
||||
|
||||
ionic.controllers.SideMenuController.call(this, {
|
||||
left: { width: 275 },
|
||||
right: { width: 275 }
|
||||
});
|
||||
|
||||
this.canDragContent = function(canDrag) {
|
||||
if (arguments.length) {
|
||||
$scope.dragContent = !!canDrag;
|
||||
}
|
||||
return $scope.dragContent;
|
||||
};
|
||||
|
||||
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'));
|
||||
};
|
||||
|
||||
$scope.sideMenuContentTranslateX = 0;
|
||||
|
||||
var deregisterInstance = $ionicSideMenuDelegate._registerInstance(
|
||||
this, $attrs.delegateHandle
|
||||
);
|
||||
$scope.$on('$destroy', deregisterInstance);
|
||||
}]);
|
||||
27
js/angular/controller/tabController.js
vendored
Normal file
27
js/angular/controller/tabController.js
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
IonicModule
|
||||
.controller('$ionicTab', [
|
||||
'$scope',
|
||||
'$ionicViewService',
|
||||
'$attrs',
|
||||
'$location',
|
||||
'$state',
|
||||
function($scope, $ionicViewService, $attrs, $location, $state) {
|
||||
this.$scope = $scope;
|
||||
|
||||
//All of these exposed for testing
|
||||
this.hrefMatchesState = function() {
|
||||
return $attrs.href && $location.path().indexOf(
|
||||
$attrs.href.replace(/^#/, '').replace(/\/$/, '')
|
||||
) === 0;
|
||||
};
|
||||
this.srefMatchesState = function() {
|
||||
return $attrs.uiSref && $state.includes( $attrs.uiSref.split('(')[0] );
|
||||
};
|
||||
this.navNameMatchesState = function() {
|
||||
return this.navViewName && $ionicViewService.isCurrentStateNavView(this.navViewName);
|
||||
};
|
||||
|
||||
this.tabMatchesState = function() {
|
||||
return this.hrefMatchesState() || this.srefMatchesState() || this.navNameMatchesState();
|
||||
};
|
||||
}]);
|
||||
97
js/angular/controller/tabsController.js
vendored
Normal file
97
js/angular/controller/tabsController.js
vendored
Normal file
@@ -0,0 +1,97 @@
|
||||
IonicModule
|
||||
.controller('$ionicTabs', [
|
||||
'$scope',
|
||||
'$ionicViewService',
|
||||
'$element',
|
||||
function($scope, $ionicViewService, $element) {
|
||||
var _selectedTab = null;
|
||||
var self = this;
|
||||
self.tabs = [];
|
||||
|
||||
self.selectedIndex = function() {
|
||||
return self.tabs.indexOf(_selectedTab);
|
||||
};
|
||||
self.selectedTab = function() {
|
||||
return _selectedTab;
|
||||
};
|
||||
|
||||
self.add = function(tab) {
|
||||
$ionicViewService.registerHistory(tab);
|
||||
self.tabs.push(tab);
|
||||
if(self.tabs.length === 1) {
|
||||
self.select(tab);
|
||||
}
|
||||
};
|
||||
|
||||
self.remove = function(tab) {
|
||||
var tabIndex = self.tabs.indexOf(tab);
|
||||
if (tabIndex === -1) {
|
||||
return;
|
||||
}
|
||||
//Use a field like '$tabSelected' so developers won't accidentally set it in controllers etc
|
||||
if (tab.$tabSelected) {
|
||||
self.deselect(tab);
|
||||
//Try to select a new tab if we're removing a tab
|
||||
if (self.tabs.length === 1) {
|
||||
//do nothing if there are no other tabs to select
|
||||
} else {
|
||||
//Select previous tab if it's the last tab, else select next tab
|
||||
var newTabIndex = tabIndex === self.tabs.length - 1 ? tabIndex - 1 : tabIndex + 1;
|
||||
self.select(self.tabs[newTabIndex]);
|
||||
}
|
||||
}
|
||||
self.tabs.splice(tabIndex, 1);
|
||||
};
|
||||
|
||||
self.deselect = function(tab) {
|
||||
if (tab.$tabSelected) {
|
||||
_selectedTab = null;
|
||||
tab.$tabSelected = false;
|
||||
(tab.onDeselect || angular.noop)();
|
||||
}
|
||||
};
|
||||
|
||||
self.select = function(tab, shouldEmitEvent) {
|
||||
var tabIndex;
|
||||
if (angular.isNumber(tab)) {
|
||||
tabIndex = tab;
|
||||
tab = self.tabs[tabIndex];
|
||||
} else {
|
||||
tabIndex = self.tabs.indexOf(tab);
|
||||
}
|
||||
if (!tab || tabIndex == -1) {
|
||||
throw new Error('Cannot select tab "' + tabIndex + '"!');
|
||||
}
|
||||
|
||||
if (_selectedTab && _selectedTab.$historyId == tab.$historyId) {
|
||||
if (shouldEmitEvent) {
|
||||
$ionicViewService.goToHistoryRoot(tab.$historyId);
|
||||
}
|
||||
} else {
|
||||
angular.forEach(self.tabs, function(tab) {
|
||||
self.deselect(tab);
|
||||
});
|
||||
|
||||
_selectedTab = tab;
|
||||
//Use a funny name like $tabSelected so the developer doesn't overwrite the var in a child scope
|
||||
tab.$tabSelected = true;
|
||||
(tab.onSelect || angular.noop)();
|
||||
|
||||
if (shouldEmitEvent) {
|
||||
var viewData = {
|
||||
type: 'tab',
|
||||
tabIndex: tabIndex,
|
||||
historyId: tab.$historyId,
|
||||
navViewName: tab.navViewName,
|
||||
hasNavView: !!tab.navViewName,
|
||||
title: tab.title,
|
||||
//Skip the first character of href if it's #
|
||||
url: tab.href,
|
||||
uiSref: tab.uiSref
|
||||
};
|
||||
$scope.$emit('viewState.changeHistory', viewData);
|
||||
}
|
||||
}
|
||||
};
|
||||
}]);
|
||||
|
||||
Reference in New Issue
Block a user