From 14a2790749f2d65ec6f0c652d5aac7a4a9d72c24 Mon Sep 17 00:00:00 2001 From: Andy Joslin Date: Mon, 14 Apr 2014 10:35:19 -0600 Subject: [PATCH] refactor(): reorganize source files --- config/build.config.js | 17 +- config/karma.conf.js | 3 +- js/angular/controller/listController.js | 115 ++++ js/angular/controller/navBarController.js | 129 +++++ js/angular/controller/scrollController.js | 186 +++++++ js/angular/controller/sideMenuController.js | 35 ++ js/angular/controller/tabController.js | 27 + js/angular/controller/tabsController.js | 97 ++++ js/{ext/angular/src => angular}/deprecated.js | 0 .../directive/actionSheet.js} | 8 +- .../directive/checkbox.js} | 7 +- js/angular/directive/content.js | 129 +++++ .../directive/headerFooterBar.js} | 14 +- js/angular/directive/infiniteScroll.js | 128 +++++ js/angular/directive/item.js | 65 +++ js/angular/directive/itemDeleteButton.js | 51 ++ js/angular/directive/itemOptionButton.js | 47 ++ js/angular/directive/itemReorderButton.js | 71 +++ js/angular/directive/list.js | 165 ++++++ js/angular/directive/menuClose.js | 29 + js/angular/directive/menuToggle.js | 40 ++ .../directive/modal.js} | 8 +- js/angular/directive/navBackButton.js | 98 ++++ js/angular/directive/navBar.js | 93 ++++ js/angular/directive/navButtons.js | 74 +++ js/angular/directive/navClear.js | 54 ++ .../directive/navView.js} | 157 +----- js/angular/directive/ngClick.js | 59 ++ js/angular/directive/pane.js | 18 + js/angular/directive/radio.js | 44 ++ js/angular/directive/refresher.js | 100 ++++ .../directive/scroll.js} | 8 +- js/angular/directive/sideMenu.js | 59 ++ js/angular/directive/sideMenuContent.js | 125 +++++ js/angular/directive/sideMenus.js | 61 ++ .../directive/slideBox.js} | 108 +--- js/angular/directive/tab.js | 136 +++++ js/angular/directive/tabNav.js | 52 ++ js/angular/directive/tabs.js | 83 +++ .../directive/toggle.js} | 13 +- .../directive/touch.js} | 0 js/angular/directive/view.js | 75 +++ js/angular/main.js | 10 + .../service/actionSheet.js} | 12 +- .../service/angularOverrides.js | 0 .../service/backdrop.js} | 5 +- .../ionicBind.js => angular/service/bind.js} | 2 +- .../service/decorators/location.js | 8 +- .../service/delegateService.js | 0 .../service/gesture.js} | 3 +- .../service/loading.js} | 21 +- .../service/modal.js} | 6 +- js/angular/service/navBarDelegate.js | 103 ++++ .../service/platform.js} | 24 +- .../service/popup.js} | 13 +- .../service/scrollDelegate.js} | 189 +------ js/angular/service/sideMenuDelegate.js | 104 ++++ js/angular/service/slideBoxDelegate.js | 97 ++++ js/angular/service/tabsDelegate.js | 68 +++ .../service/templateLoader.js} | 6 +- .../service/viewService.js} | 39 +- js/controllers/navController.js | 152 ----- js/controllers/tabBarController.js | 143 ----- js/ext/angular/src/directive/ionicContent.js | 383 ------------- js/ext/angular/src/directive/ionicList.js | 520 ------------------ js/ext/angular/src/directive/ionicNavBar.js | 491 ----------------- js/ext/angular/src/directive/ionicRadio.js | 130 ----- js/ext/angular/src/directive/ionicSideMenu.js | 465 ---------------- js/ext/angular/src/directive/ionicTabBar.js | 454 --------------- .../angular/src/directive/ionicVirtRepeat.js | 24 - .../src/directive/ionicVirtualRepeat.js | 328 ----------- js/ext/angular/src/ionicAngular.js | 50 -- js/ext/angular/test/actionSheet.html | 161 ------ js/ext/angular/test/loading.html | 29 - js/ext/angular/test/scroll.html | 134 ----- js/views/loadingView.js | 56 -- js/views/navBarView.js | 53 -- js/views/tabBarView.js | 224 -------- test/css/actionsheet.html | 76 +++ test/{html => css}/bars-clear.html | 0 test/{html => css}/biglists.html | 0 test/{html => css}/button-bar.html | 0 test/{html => css}/buttons.html | 0 test/{html => css}/cards.html | 0 test/{html => css}/colors.html | 0 test/{html => css}/footers.html | 0 test/{html => css}/grid.html | 0 test/{html => css}/headers.html | 0 test/{html => css}/input-checkbox.html | 0 test/{html => css}/input-radio.html | 0 test/{html => css}/input-range.html | 0 test/{html => css}/input-select.html | 0 test/{html => css}/input-text.html | 0 test/{html => css}/input-textarea.html | 0 test/{html => css}/input-toggle.html | 0 test/{html => css}/lists.html | 0 test/css/loading.html | 24 + test/{html => css}/modals.html | 0 test/{html => css}/progress.html | 0 test/css/scroll.html | 49 ++ test/{html => css}/search-ios7.html | 0 test/{html => css}/search.html | 0 test/{html => css}/side-menus.html | 0 test/{html => css}/splitPane.html | 0 test/{html => css}/status-bar.html | 0 test/{html => css}/tab-bars-icons-bottom.html | 0 test/{html => css}/tab-bars-icons-left.html | 0 test/{html => css}/tab-bars-icons-right.html | 0 test/{html => css}/tab-bars-no-icons.html | 0 test/{html => css}/tab-bars-only-icons.html | 0 test/{html => css}/tab-bars.html | 0 test/{html => css}/tab-with-footer.html | 0 .../angular/test => test/css}/tree_bark.png | Bin test/{html => css}/type.html | 0 test/html/actionsheet.html | 211 ++++--- .../test => test/html}/anchorScroll.html | 0 .../angular/test => test/html}/app_icon.png | Bin .../angular/test => test/html}/carousel.html | 0 .../test => test/html}/clickTests.html | 0 .../angular/test => test/html}/content.html | 0 .../test => test/html}/contentClick.html | 0 .../test => test/html}/content_defer.html | 0 .../angular/test => test/html}/content_h.html | 0 test/html/controllers/nav.html | 95 ---- test/html/controllers/route.html | 35 -- test/html/controllers/sideMenu.html | 81 --- test/html/controllers/tabBar.html | 108 ---- test/html/controllers/tabs.html | 109 ---- .../angular/test => test/html}/dom-trace.js | 0 .../test => test/html}/embeddedObject.html | 0 .../angular/test => test/html}/gesture.html | 0 .../html}/has-anything-dynamic.html | 0 .../angular/test => test/html}/header.html | 0 .../angular/test => test/html}/history.html | 0 {js/ext/angular/test => test/html}/input.html | 0 .../angular/test => test/html}/list-fit.html | 0 {js/ext/angular/test => test/html}/list.html | 0 test/html/loading.html | 35 +- {js/ext/angular/test => test/html}/map.html | 0 {js/ext/angular/test => test/html}/modal.html | 0 .../test => test/html}/nestedScroll.html | 0 .../angular/test => test/html}/overflow.html | 0 {js/ext/angular/test => test/html}/poly.html | 0 {js/ext/angular/test => test/html}/popup.html | 0 .../test => test/html}/rememberScroll.html | 0 test/html/scroll.html | 157 ++++-- .../angular/test => test/html}/scroll2.html | 0 .../angular/test => test/html}/sideMenu.html | 0 .../angular/test => test/html}/sideMenu2.html | 0 .../angular/test => test/html}/slideBox.html | 0 .../test => test/html}/slideBoxDynamic.html | 0 .../test => test/html}/subControllers.html | 0 .../test => test/html}/tabs-repeat.html | 0 {js/ext/angular/test => test/html}/tabs.html | 0 .../angular/test => test/html}/tapInputs.html | 0 .../angular/test => test/html}/toggle.html | 0 .../angular/test => test/html}/viewState.html | 0 .../controller/scrollController.unit.js | 0 .../unit/angular/directive/backdrop.unit.js | 0 .../unit/angular/directive/checkbox.unit.js | 2 +- .../unit/angular/directive/content.unit.js | 2 +- .../angular/directive/headerFooterBar.unit.js | 0 .../angular/directive/infiniteScroll.unit.js | 0 .../unit/angular/directive/list.unit.js | 4 + .../angular/directive/navBackButton.unit.js | 0 .../unit/angular/directive/navBar.unit.js | 4 +- .../unit/angular/directive/navClear.unit.js | 0 .../unit/angular/directive/navView.unit.js | 2 +- .../unit/angular/directive/refresher.unit.js | 0 .../unit/angular/directive/scroll.unit.js | 0 .../unit/angular/directive/sideMenu.unit.js | 4 +- .../unit/angular/directive/slideBox.unit.js | 0 .../unit/angular/directive/tabs.unit.js | 11 +- .../unit/angular/directive/toggle.unit.js | 0 .../unit/angular/directive/view.unit.js | 2 +- .../unit/angular/service/actionSheet.unit.js | 3 +- .../unit/angular/service/activator.unit.js | 0 .../angular}/service/angularOverrides.unit.js | 0 .../unit/angular/service/bind.unit.js | 2 +- .../service/decorators/location.unit.js | 2 +- .../angular}/service/delegateService.unit.js | 0 .../unit/angular/service/gesture.unit.js | 2 +- .../unit/angular/service/loading.unit.js | 0 .../unit/angular/service/modal.unit.js | 22 +- .../unit/angular/service/platform.unit.js | 7 +- .../unit/angular/service/popup.unit.js | 0 .../unit/angular/service/tap.unit.js | 0 .../angular/service/templateLoader.unit.js | 0 .../unit/angular/service/viewService.unit.js | 5 +- test/unit/controllers/navController.unit.js | 60 -- .../unit/controllers/tabBarController.unit.js | 88 --- test/unit/views/tabBar.unit.js | 147 ----- 192 files changed, 3407 insertions(+), 5237 deletions(-) create mode 100644 js/angular/controller/listController.js create mode 100644 js/angular/controller/navBarController.js create mode 100644 js/angular/controller/scrollController.js create mode 100644 js/angular/controller/sideMenuController.js create mode 100644 js/angular/controller/tabController.js create mode 100644 js/angular/controller/tabsController.js rename js/{ext/angular/src => angular}/deprecated.js (100%) rename js/{ext/angular/src/directive/ionicActionSheet.js => angular/directive/actionSheet.js} (95%) rename js/{ext/angular/src/directive/ionicCheckbox.js => angular/directive/checkbox.js} (95%) create mode 100644 js/angular/directive/content.js rename js/{ext/angular/src/directive/ionicBar.js => angular/directive/headerFooterBar.js} (94%) create mode 100644 js/angular/directive/infiniteScroll.js create mode 100644 js/angular/directive/item.js create mode 100644 js/angular/directive/itemDeleteButton.js create mode 100644 js/angular/directive/itemOptionButton.js create mode 100644 js/angular/directive/itemReorderButton.js create mode 100644 js/angular/directive/list.js create mode 100644 js/angular/directive/menuClose.js create mode 100644 js/angular/directive/menuToggle.js rename js/{ext/angular/src/directive/ionicModal.js => angular/directive/modal.js} (82%) create mode 100644 js/angular/directive/navBackButton.js create mode 100644 js/angular/directive/navBar.js create mode 100644 js/angular/directive/navButtons.js create mode 100644 js/angular/directive/navClear.js rename js/{ext/angular/src/directive/ionicViewState.js => angular/directive/navView.js} (62%) create mode 100644 js/angular/directive/ngClick.js create mode 100644 js/angular/directive/pane.js create mode 100644 js/angular/directive/radio.js create mode 100644 js/angular/directive/refresher.js rename js/{ext/angular/src/directive/ionicScroll.js => angular/directive/scroll.js} (97%) create mode 100644 js/angular/directive/sideMenu.js create mode 100644 js/angular/directive/sideMenuContent.js create mode 100644 js/angular/directive/sideMenus.js rename js/{ext/angular/src/directive/ionicSlideBox.js => angular/directive/slideBox.js} (67%) create mode 100644 js/angular/directive/tab.js create mode 100644 js/angular/directive/tabNav.js create mode 100644 js/angular/directive/tabs.js rename js/{ext/angular/src/directive/ionicToggle.js => angular/directive/toggle.js} (92%) rename js/{ext/angular/src/directive/ionicTouch.js => angular/directive/touch.js} (100%) create mode 100644 js/angular/directive/view.js create mode 100644 js/angular/main.js rename js/{ext/angular/src/service/ionicActionSheet.js => angular/service/actionSheet.js} (94%) rename js/{ext/angular/src => angular}/service/angularOverrides.js (100%) rename js/{ext/angular/src/service/ionicBackdrop.js => angular/service/backdrop.js} (97%) rename js/{ext/angular/src/service/ionicBind.js => angular/service/bind.js} (97%) rename js/{ext/angular/src => angular}/service/decorators/location.js (88%) rename js/{ext/angular/src => angular}/service/delegateService.js (100%) rename js/{ext/angular/src/service/ionicGesture.js => angular/service/gesture.js} (96%) rename js/{ext/angular/src/service/ionicLoading.js => angular/service/loading.js} (89%) rename js/{ext/angular/src/service/ionicModal.js => angular/service/modal.js} (98%) create mode 100644 js/angular/service/navBarDelegate.js rename js/{ext/angular/src/service/ionicPlatform.js => angular/service/platform.js} (88%) rename js/{ext/angular/src/service/ionicPopup.js => angular/service/popup.js} (98%) rename js/{ext/angular/src/controller/ionicScrollController.js => angular/service/scrollDelegate.js} (53%) create mode 100644 js/angular/service/sideMenuDelegate.js create mode 100644 js/angular/service/slideBoxDelegate.js create mode 100644 js/angular/service/tabsDelegate.js rename js/{ext/angular/src/service/ionicTemplateLoader.js => angular/service/templateLoader.js} (95%) rename js/{ext/angular/src/service/ionicView.js => angular/service/viewService.js} (95%) delete mode 100644 js/controllers/navController.js delete mode 100644 js/controllers/tabBarController.js delete mode 100644 js/ext/angular/src/directive/ionicContent.js delete mode 100644 js/ext/angular/src/directive/ionicList.js delete mode 100644 js/ext/angular/src/directive/ionicNavBar.js delete mode 100644 js/ext/angular/src/directive/ionicRadio.js delete mode 100644 js/ext/angular/src/directive/ionicSideMenu.js delete mode 100644 js/ext/angular/src/directive/ionicTabBar.js delete mode 100644 js/ext/angular/src/directive/ionicVirtRepeat.js delete mode 100644 js/ext/angular/src/directive/ionicVirtualRepeat.js delete mode 100644 js/ext/angular/src/ionicAngular.js delete mode 100644 js/ext/angular/test/actionSheet.html delete mode 100644 js/ext/angular/test/loading.html delete mode 100644 js/ext/angular/test/scroll.html delete mode 100644 js/views/loadingView.js delete mode 100644 js/views/navBarView.js delete mode 100644 js/views/tabBarView.js create mode 100644 test/css/actionsheet.html rename test/{html => css}/bars-clear.html (100%) rename test/{html => css}/biglists.html (100%) rename test/{html => css}/button-bar.html (100%) rename test/{html => css}/buttons.html (100%) rename test/{html => css}/cards.html (100%) rename test/{html => css}/colors.html (100%) rename test/{html => css}/footers.html (100%) rename test/{html => css}/grid.html (100%) rename test/{html => css}/headers.html (100%) rename test/{html => css}/input-checkbox.html (100%) rename test/{html => css}/input-radio.html (100%) rename test/{html => css}/input-range.html (100%) rename test/{html => css}/input-select.html (100%) rename test/{html => css}/input-text.html (100%) rename test/{html => css}/input-textarea.html (100%) rename test/{html => css}/input-toggle.html (100%) rename test/{html => css}/lists.html (100%) create mode 100644 test/css/loading.html rename test/{html => css}/modals.html (100%) rename test/{html => css}/progress.html (100%) create mode 100644 test/css/scroll.html rename test/{html => css}/search-ios7.html (100%) rename test/{html => css}/search.html (100%) rename test/{html => css}/side-menus.html (100%) rename test/{html => css}/splitPane.html (100%) rename test/{html => css}/status-bar.html (100%) rename test/{html => css}/tab-bars-icons-bottom.html (100%) rename test/{html => css}/tab-bars-icons-left.html (100%) rename test/{html => css}/tab-bars-icons-right.html (100%) rename test/{html => css}/tab-bars-no-icons.html (100%) rename test/{html => css}/tab-bars-only-icons.html (100%) rename test/{html => css}/tab-bars.html (100%) rename test/{html => css}/tab-with-footer.html (100%) rename {js/ext/angular/test => test/css}/tree_bark.png (100%) rename test/{html => css}/type.html (100%) rename {js/ext/angular/test => test/html}/anchorScroll.html (100%) rename {js/ext/angular/test => test/html}/app_icon.png (100%) rename {js/ext/angular/test => test/html}/carousel.html (100%) rename {js/ext/angular/test => test/html}/clickTests.html (100%) rename {js/ext/angular/test => test/html}/content.html (100%) rename {js/ext/angular/test => test/html}/contentClick.html (100%) rename {js/ext/angular/test => test/html}/content_defer.html (100%) rename {js/ext/angular/test => test/html}/content_h.html (100%) delete mode 100644 test/html/controllers/nav.html delete mode 100644 test/html/controllers/route.html delete mode 100644 test/html/controllers/sideMenu.html delete mode 100644 test/html/controllers/tabBar.html delete mode 100644 test/html/controllers/tabs.html rename {js/ext/angular/test => test/html}/dom-trace.js (100%) rename {js/ext/angular/test => test/html}/embeddedObject.html (100%) rename {js/ext/angular/test => test/html}/gesture.html (100%) rename {js/ext/angular/test => test/html}/has-anything-dynamic.html (100%) rename {js/ext/angular/test => test/html}/header.html (100%) rename {js/ext/angular/test => test/html}/history.html (100%) rename {js/ext/angular/test => test/html}/input.html (100%) rename {js/ext/angular/test => test/html}/list-fit.html (100%) rename {js/ext/angular/test => test/html}/list.html (100%) rename {js/ext/angular/test => test/html}/map.html (100%) rename {js/ext/angular/test => test/html}/modal.html (100%) rename {js/ext/angular/test => test/html}/nestedScroll.html (100%) rename {js/ext/angular/test => test/html}/overflow.html (100%) rename {js/ext/angular/test => test/html}/poly.html (100%) rename {js/ext/angular/test => test/html}/popup.html (100%) rename {js/ext/angular/test => test/html}/rememberScroll.html (100%) rename {js/ext/angular/test => test/html}/scroll2.html (100%) rename {js/ext/angular/test => test/html}/sideMenu.html (100%) rename {js/ext/angular/test => test/html}/sideMenu2.html (100%) rename {js/ext/angular/test => test/html}/slideBox.html (100%) rename {js/ext/angular/test => test/html}/slideBoxDynamic.html (100%) rename {js/ext/angular/test => test/html}/subControllers.html (100%) rename {js/ext/angular/test => test/html}/tabs-repeat.html (100%) rename {js/ext/angular/test => test/html}/tabs.html (100%) rename {js/ext/angular/test => test/html}/tapInputs.html (100%) rename {js/ext/angular/test => test/html}/toggle.html (100%) rename {js/ext/angular/test => test/html}/viewState.html (100%) rename js/ext/angular/test/controller/ionicScrollController.unit.js => test/unit/angular/controller/scrollController.unit.js (100%) rename js/ext/angular/test/directive/ionicBackdrop.unit.js => test/unit/angular/directive/backdrop.unit.js (100%) rename js/ext/angular/test/directive/ionicCheckbox.unit.js => test/unit/angular/directive/checkbox.unit.js (96%) rename js/ext/angular/test/directive/ionicContent.unit.js => test/unit/angular/directive/content.unit.js (99%) rename js/ext/angular/test/directive/ionicBar.unit.js => test/unit/angular/directive/headerFooterBar.unit.js (100%) rename js/ext/angular/test/directive/ionicInfiniteScroll.unit.js => test/unit/angular/directive/infiniteScroll.unit.js (100%) rename js/ext/angular/test/directive/ionicList.unit.js => test/unit/angular/directive/list.unit.js (99%) rename js/ext/angular/test/directive/ionicNavBackButton.unit.js => test/unit/angular/directive/navBackButton.unit.js (100%) rename js/ext/angular/test/directive/ionicNavBar.unit.js => test/unit/angular/directive/navBar.unit.js (98%) rename js/ext/angular/test/directive/ionicNavClear.unit.js => test/unit/angular/directive/navClear.unit.js (100%) rename js/ext/angular/test/directive/ionicNavView.unit.js => test/unit/angular/directive/navView.unit.js (91%) rename js/ext/angular/test/directive/ionicRefresher.unit.js => test/unit/angular/directive/refresher.unit.js (100%) rename js/ext/angular/test/directive/ionicScroll.unit.js => test/unit/angular/directive/scroll.unit.js (100%) rename js/ext/angular/test/directive/ionicSideMenu.unit.js => test/unit/angular/directive/sideMenu.unit.js (98%) rename js/ext/angular/test/directive/ionicSlideBox.unit.js => test/unit/angular/directive/slideBox.unit.js (100%) rename js/ext/angular/test/directive/ionicTabBar.unit.js => test/unit/angular/directive/tabs.unit.js (98%) rename js/ext/angular/test/directive/ionicToggle.unit.js => test/unit/angular/directive/toggle.unit.js (100%) rename js/ext/angular/test/directive/ionicView.unit.js => test/unit/angular/directive/view.unit.js (98%) rename js/ext/angular/test/service/ionicActionSheet.unit.js => test/unit/angular/service/actionSheet.unit.js (93%) rename js/ext/angular/test/service/ionicActivator.unit.js => test/unit/angular/service/activator.unit.js (100%) rename {js/ext/angular/test => test/unit/angular}/service/angularOverrides.unit.js (100%) rename js/ext/angular/test/service/ionicBind.unit.js => test/unit/angular/service/bind.unit.js (98%) rename {js/ext/angular/test => test/unit/angular}/service/decorators/location.unit.js (91%) rename {js/ext/angular/test => test/unit/angular}/service/delegateService.unit.js (100%) rename js/ext/angular/test/service/ionicGesture.unit.js => test/unit/angular/service/gesture.unit.js (96%) rename js/ext/angular/test/service/ionicLoading.unit.js => test/unit/angular/service/loading.unit.js (100%) rename js/ext/angular/test/service/ionicModal.unit.js => test/unit/angular/service/modal.unit.js (92%) rename js/ext/angular/test/service/ionicPlatform.unit.js => test/unit/angular/service/platform.unit.js (97%) rename js/ext/angular/test/service/ionicPopup.unit.js => test/unit/angular/service/popup.unit.js (100%) rename js/ext/angular/test/service/ionicTap.unit.js => test/unit/angular/service/tap.unit.js (100%) rename js/ext/angular/test/service/ionicTemplateLoader.unit.js => test/unit/angular/service/templateLoader.unit.js (100%) rename js/ext/angular/test/service/ionicViewService.unit.js => test/unit/angular/service/viewService.unit.js (99%) delete mode 100644 test/unit/controllers/navController.unit.js delete mode 100644 test/unit/controllers/tabBarController.unit.js delete mode 100644 test/unit/views/tabBar.unit.js diff --git a/config/build.config.js b/config/build.config.js index ceef7187a5..dae8d1b532 100644 --- a/config/build.config.js +++ b/config/build.config.js @@ -45,34 +45,25 @@ module.exports = { // Views 'js/views/view.js', - 'js/views/scrollView.js', - 'js/views/actionSheetView.js', 'js/views/headerBarView.js', 'js/views/listView.js', - 'js/views/loadingView.js', 'js/views/modalView.js', - 'js/views/navBarView.js', 'js/views/sideMenuView.js', 'js/views/sliderView.js', - 'js/views/tabBarView.js', 'js/views/toggleView.js', // Controllers 'js/controllers/viewController.js', - - 'js/controllers/navController.js', 'js/controllers/sideMenuController.js', - 'js/controllers/tabBarController.js' - ], angularIonicFiles: [ - 'js/ext/angular/src/*.js', - 'js/ext/angular/src/service/**/*.js', - 'js/ext/angular/src/directive/**/*.js', - 'js/ext/angular/src/controller/**/*.js' + 'js/angular/*.js', + 'js/angular/service/**/*.js', + 'js/angular/controller/**/*.js', + 'js/angular/directive/**/*.js', ], //Which vendor files to include in dist, used by build diff --git a/config/karma.conf.js b/config/karma.conf.js index 9f4393e547..f1d9db898f 100644 --- a/config/karma.conf.js +++ b/config/karma.conf.js @@ -25,8 +25,7 @@ module.exports = function(config) { .concat(buildConfig.ionicFiles) .concat(buildConfig.angularIonicFiles) .concat([ - 'test/unit/**/*.js', - 'js/ext/angular/test/**/*.js' + 'test/unit/**/*.js' ]), // list of files to exclude diff --git a/js/angular/controller/listController.js b/js/angular/controller/listController.js new file mode 100644 index 0000000000..2f4f4ac825 --- /dev/null +++ b/js/angular/controller/listController.js @@ -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 + * + * + * + * > + * {% raw %}Hello, {{i}}!{% endraw %} + * + * + * + * + * ``` + * ```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(); + }; +}]); diff --git a/js/angular/controller/navBarController.js b/js/angular/controller/navBarController.js new file mode 100644 index 0000000000..5fe099bd18 --- /dev/null +++ b/js/angular/controller/navBarController.js @@ -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('

')($scope); + angular.element(currentTitles[0]).replaceWith(oldTitleEl); + } + //Compile new title + newTitleEl = $compile('

')($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'); + }); + }); + }; +}]) + diff --git a/js/angular/controller/scrollController.js b/js/angular/controller/scrollController.js new file mode 100644 index 0000000000..3c128e4e1b --- /dev/null +++ b/js/angular/controller/scrollController.js @@ -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(); + }); + }; +}]); + diff --git a/js/angular/controller/sideMenuController.js b/js/angular/controller/sideMenuController.js new file mode 100644 index 0000000000..e333c463f4 --- /dev/null +++ b/js/angular/controller/sideMenuController.js @@ -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); +}]); diff --git a/js/angular/controller/tabController.js b/js/angular/controller/tabController.js new file mode 100644 index 0000000000..d6074a14e2 --- /dev/null +++ b/js/angular/controller/tabController.js @@ -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(); + }; +}]); diff --git a/js/angular/controller/tabsController.js b/js/angular/controller/tabsController.js new file mode 100644 index 0000000000..cf68e4ad79 --- /dev/null +++ b/js/angular/controller/tabsController.js @@ -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); + } + } + }; +}]); + diff --git a/js/ext/angular/src/deprecated.js b/js/angular/deprecated.js similarity index 100% rename from js/ext/angular/src/deprecated.js rename to js/angular/deprecated.js diff --git a/js/ext/angular/src/directive/ionicActionSheet.js b/js/angular/directive/actionSheet.js similarity index 95% rename from js/ext/angular/src/directive/ionicActionSheet.js rename to js/angular/directive/actionSheet.js index 6615c7ff8a..b618b5dd12 100644 --- a/js/ext/angular/src/directive/ionicActionSheet.js +++ b/js/angular/directive/actionSheet.js @@ -1,12 +1,8 @@ -(function() { -'use strict'; - -angular.module('ionic.ui.actionSheet', []) - /* * We don't document the ionActionSheet directive, we instead document * the $ionicActionSheet service */ +IonicModule .directive('ionActionSheet', ['$document', function($document) { return { restrict: 'E', @@ -52,5 +48,3 @@ angular.module('ionic.ui.actionSheet', []) '' }; }]); - -})(); diff --git a/js/ext/angular/src/directive/ionicCheckbox.js b/js/angular/directive/checkbox.js similarity index 95% rename from js/ext/angular/src/directive/ionicCheckbox.js rename to js/angular/directive/checkbox.js index f183dd10b7..5b9c8af3d1 100644 --- a/js/ext/angular/src/directive/ionicCheckbox.js +++ b/js/angular/directive/checkbox.js @@ -1,7 +1,3 @@ -(function() { -'use strict'; - -angular.module('ionic.ui.checkbox', []) /** * @ngdoc directive @@ -19,6 +15,7 @@ angular.module('ionic.ui.checkbox', []) * Checkbox Label * ``` */ +IonicModule .directive('ionCheckbox', function() { return { restrict: 'E', @@ -52,5 +49,3 @@ angular.module('ionic.ui.checkbox', []) }; }); - -})(); diff --git a/js/angular/directive/content.js b/js/angular/directive/content.js new file mode 100644 index 0000000000..610dd677c1 --- /dev/null +++ b/js/angular/directive/content.js @@ -0,0 +1,129 @@ +/** + * @ngdoc directive + * @name ionContent + * @module ionic + * @delegate ionic.service:$ionicScrollDelegate + * @restrict E + * + * @description + * The ionContent directive provides an easy to use content area that can be configured + * to use Ionic's custom Scroll View, or the built in overflow scrolling of the browser. + * + * While we recommend using the custom Scroll features in Ionic in most cases, sometimes + * (for performance reasons) only the browser's native overflow scrolling will suffice, + * and so we've made it easy to toggle between the Ionic scroll implementation and + * overflow scrolling. + * + * You can implement pull-to-refresh with the {@link ionic.directive:ionRefresher} + * directive, and infinite scrolling with the {@link ionic.directive:ionInfiniteScroll} + * directive. + * + * @param {string=} delegate-handle The handle used to identify this scrollView + * with {@link ionic.service:$ionicScrollDelegate}. + * @param {boolean=} padding Whether to add padding to the content. + * of the content. Defaults to true on iOS, false on Android. + * @param {boolean=} scroll Whether to allow scrolling of content. Defaults to true. + * @param {boolean=} overflow-scroll Whether to use overflow-scrolling instead of + * Ionic scroll. + * @param {boolean=} has-bouncing Whether to allow scrolling to bounce past the edges + * 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. + */ +IonicModule +.directive('ionContent', [ + '$timeout', + '$controller', + '$ionicBind', +function($timeout, $controller, $ionicBind) { + return { + restrict: 'E', + require: '^?ionNavView', + scope: true, + compile: function(element, attr) { + var innerElement; + + element.addClass('scroll-content'); + + if (attr.scroll != 'false') { + //We cannot use normal transclude here because it breaks element.data() + //inheritance on compile + innerElement = angular.element('
'); + innerElement.append(element.contents()); + element.append(innerElement); + } + + return { pre: prelink }; + function prelink($scope, $element, $attr, navViewCtrl) { + var parentScope = $scope.$parent; + $scope.$watch(function() { + return (parentScope.$hasHeader ? ' has-header' : '') + + (parentScope.$hasSubheader ? ' has-subheader' : '') + + (parentScope.$hasFooter ? ' has-footer' : '') + + (parentScope.$hasSubfooter ? ' has-subfooter' : '') + + (parentScope.$hasTabs ? ' has-tabs' : '') + + (parentScope.$hasTabsTop ? ' has-tabs-top' : ''); + }, function(className, oldClassName) { + $element.removeClass(oldClassName); + $element.addClass(className); + }); + + //Only this ionContent should use these variables from parent scopes + $scope.$hasHeader = $scope.$hasSubheader = + $scope.$hasFooter = $scope.$hasSubfooter = + $scope.$hasTabs = $scope.$hasTabsTop = + false; + + $ionicBind($scope, $attr, { + $onScroll: '&onScroll', + $onScrollComplete: '&onScrollComplete', + hasBouncing: '@', + scroll: '@', + padding: '@', + hasScrollX: '@', + hasScrollY: '@', + scrollbarX: '@', + scrollbarY: '@', + startX: '@', + startY: '@', + scrollEventInterval: '@' + }); + + if (angular.isDefined($attr.padding)) { + $scope.$watch($attr.padding, function(newVal) { + (innerElement || $element).toggleClass('padding', !!newVal); + }); + } + + if ($scope.scroll === "false") { + //do nothing + } else if(attr.overflowScroll === "true") { + $element.addClass('overflow-scroll'); + } else { + $controller('$ionicScroll', { + $scope: $scope, + scrollViewOptions: { + el: $element[0], + delegateHandle: attr.delegateHandle, + bouncing: $scope.$eval($scope.hasBouncing), + startX: $scope.$eval($scope.startX) || 0, + startY: $scope.$eval($scope.startY) || 0, + scrollbarX: $scope.$eval($scope.scrollbarX) !== false, + scrollbarY: $scope.$eval($scope.scrollbarY) !== false, + scrollingX: $scope.$eval($scope.hasScrollX) === true, + scrollingY: $scope.$eval($scope.hasScrollY) !== false, + scrollEventInterval: parseInt($scope.scrollEventInterval, 10) || 20, + scrollingComplete: function() { + $scope.$onScrollComplete({ + scrollTop: this.__scrollTop, + scrollLeft: this.__scrollLeft + }); + } + } + }); + } + + } + } + }; +}]); diff --git a/js/ext/angular/src/directive/ionicBar.js b/js/angular/directive/headerFooterBar.js similarity index 94% rename from js/ext/angular/src/directive/ionicBar.js rename to js/angular/directive/headerFooterBar.js index 1cfd765d41..b2e1b1b3df 100644 --- a/js/ext/angular/src/directive/ionicBar.js +++ b/js/angular/directive/headerFooterBar.js @@ -1,8 +1,5 @@ -(function(ionic) { -'use strict'; - -angular.module('ionic.ui.header', ['ngAnimate', 'ngSanitize']) +IonicModule .directive('ionNavBar', tapScrollToTopDirective()) .directive('ionHeaderBar', tapScrollToTopDirective()) @@ -37,7 +34,7 @@ angular.module('ionic.ui.header', ['ngAnimate', 'ngSanitize']) * * ``` */ -.directive('ionHeaderBar', barDirective(true)) +.directive('ionHeaderBar', headerFooterBarDirective(true)) /** * @ngdoc directive @@ -70,7 +67,7 @@ angular.module('ionic.ui.header', ['ngAnimate', 'ngSanitize']) * * ``` */ -.directive('ionFooterBar', barDirective(false)); +.directive('ionFooterBar', headerFooterBarDirective(false)); function tapScrollToTopDirective() { return ['$ionicScrollDelegate', function($ionicScrollDelegate) { @@ -101,8 +98,7 @@ function tapScrollToTopDirective() { }]; } - -function barDirective(isHeader) { +function headerFooterBarDirective(isHeader) { return [function() { return { restrict: 'E', @@ -147,5 +143,3 @@ function barDirective(isHeader) { }; }]; } - -})(ionic); diff --git a/js/angular/directive/infiniteScroll.js b/js/angular/directive/infiniteScroll.js new file mode 100644 index 0000000000..631fffcf83 --- /dev/null +++ b/js/angular/directive/infiniteScroll.js @@ -0,0 +1,128 @@ +/** + * @ngdoc directive + * @name ionInfiniteScroll + * @module ionic + * @parent ionic.directive:ionContent, ionic.directive:ionScroll + * @restrict E + * + * @description + * The ionInfiniteScroll directive allows you to call a function whenever + * the user gets to the bottom of the page or near the bottom of the page. + * + * The expression you pass in for `on-infinite` is called when the user scrolls + * greater than `distance` away from the bottom of the content. + * + * @param {expression} on-infinite What to call when the scroller reaches the + * bottom. + * @param {string=} distance The distance from the bottom that the scroll must + * reach to trigger the on-infinite expression. Default: 1%. + * @param {string=} icon The icon to show while loading. Default: 'ion-loading-d'. + * + * @usage + * ```html + * + * + * + * + * ``` + * ```js + * function MyController($scope, $http) { + * $scope.items = []; + * $scope.loadMore = function() { + * $http.get('/more-items').success(function(items) { + * useItems(items); + * $scope.$broadcast('scroll.infiniteScrollComplete'); + * }); + * }; + * } + * ``` + * + * An easy to way to stop infinite scroll once there is no more data to load + * is to use angular's `ng-if` directive: + * + * ```html + * + * + * ``` + */ +IonicModule +.directive('ionInfiniteScroll', ['$timeout', function($timeout) { + function calculateMaxValue(distance, maximum, isPercent) { + return isPercent ? + maximum * (1 - parseInt(distance,10) / 100) : + maximum - parseInt(distance, 10); + } + return { + restrict: 'E', + require: ['^$ionicScroll', 'ionInfiniteScroll'], + template: + '
' + + '
' + + '' + + '
' + + '
', + scope: true, + controller: ['$scope', '$attrs', function($scope, $attrs) { + this.isLoading = false; + this.scrollView = null; //given by link function + this.getMaxScroll = function() { + var distance = ($attrs.distance || '1%').trim(); + var isPercent = distance.indexOf('%') !== -1; + var maxValues = this.scrollView.getScrollMax(); + return { + left: this.scrollView.options.scrollingX ? + calculateMaxValue(distance, maxValues.left, isPercent) : + -1, + top: this.scrollView.options.scrollingY ? + calculateMaxValue(distance, maxValues.top, isPercent) : + -1 + }; + }; + }], + link: function($scope, $element, $attrs, ctrls) { + var scrollCtrl = ctrls[0]; + var infiniteScrollCtrl = ctrls[1]; + var scrollView = infiniteScrollCtrl.scrollView = scrollCtrl.scrollView; + + $scope.icon = function() { + return angular.isDefined($attrs.icon) ? $attrs.icon : 'ion-loading-d'; + }; + + $scope.$on('scroll.infiniteScrollComplete', function() { + $element[0].classList.remove('active'); + $timeout(function() { + scrollView.resize(); + }, 0, false); + infiniteScrollCtrl.isLoading = false; + }); + $scope.$on('$destroy', function() { + scrollCtrl.$element.off('scroll', checkBounds); + }); + + var checkBounds = ionic.animationFrameThrottle(checkInfiniteBounds); + + //Check bounds on start, after scrollView is fully rendered + setTimeout(checkBounds); + scrollCtrl.$element.on('scroll', checkBounds); + + function checkInfiniteBounds() { + if (infiniteScrollCtrl.isLoading) return; + + var scrollValues = scrollView.getValues(); + var maxScroll = infiniteScrollCtrl.getMaxScroll(); + + if ((maxScroll.left !== -1 && scrollValues.left >= maxScroll.left) || + (maxScroll.top !== -1 && scrollValues.top >= maxScroll.top)) { + $element[0].classList.add('active'); + infiniteScrollCtrl.isLoading = true; + $scope.$parent && $scope.$parent.$apply($attrs.onInfinite || ''); + } + } + } + }; +}]); diff --git a/js/angular/directive/item.js b/js/angular/directive/item.js new file mode 100644 index 0000000000..3f0d52412e --- /dev/null +++ b/js/angular/directive/item.js @@ -0,0 +1,65 @@ +var ITEM_TPL_CONTENT_ANCHOR = + ''; +var ITEM_TPL_CONTENT = + '
'; +/** +* @ngdoc directive +* @name ionItem +* @parent ionic.directive:ionList +* @module ionic +* @restrict E +* Creates a list-item that can easily be swiped, +* deleted, reordered, edited, and more. +* +* See {@link ionic.directive:ionList} for a complete example & explanation. +* +* Can be assigned any item class name. See the +* [list CSS documentation](/docs/components/#list). +* +* @usage +* +* ```html +* +* Hello! +* +* ``` +*/ +IonicModule +.directive('ionItem', [ + '$animate', + '$compile', +function($animate, $compile) { + return { + restrict: 'E', + controller: ['$scope', '$element', function($scope, $element) { + this.$scope = $scope; + this.$element = $element; + }], + priorty: Number.MAX_VALUE, + require: ['ionItem', '^ionList'], + scope: true, + compile: function($element, $attrs) { + var isAnchor = angular.isDefined($attrs.href) || angular.isDefined($attrs.ngHref); + var isComplexItem = isAnchor || + //Lame way of testing, but we have to know at compile what to do with the element + /ion-(delete|option|reorder)-button/.test($element.html()); + + if (isComplexItem) { + var innerElement = angular.element(isAnchor ? ITEM_TPL_CONTENT_ANCHOR : ITEM_TPL_CONTENT); + innerElement.append($element.contents()); + + $element.append(innerElement); + $element.addClass('item item-complex'); + } else { + $element.addClass('item'); + } + + return function link($scope, $element, $attrs) { + $scope.$href = function() { + return $attrs.href || $attrs.ngHref; + }; + }; + } + }; +}]); + diff --git a/js/angular/directive/itemDeleteButton.js b/js/angular/directive/itemDeleteButton.js new file mode 100644 index 0000000000..19059e3c24 --- /dev/null +++ b/js/angular/directive/itemDeleteButton.js @@ -0,0 +1,51 @@ +var ITEM_TPL_DELETE_BUTTON = + '
' + + '
'; +/** +* @ngdoc directive +* @name ionDeleteButton +* @parent ionic.directive:ionItem +* @module ionic +* @restrict E +* Creates a delete button inside a list item, that is visible when the +* {@link ionic.directive:ionList ionList parent's} `show-delete` evaluates to true or +* `$ionicListDelegate.showDelete(true)` is called. +* +* Takes any ionicon as a class. +* +* See {@link ionic.directive:ionList} for a complete example & explanation. +* +* @usage +* +* ```html +* +* +* +* Hello, list item! +* +* +* +* Show Delete? +* +* ``` +*/ +IonicModule +.directive('ionDeleteButton', [function() { + return { + restrict: 'E', + require: '^ionItem', + //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, + compile: function($element, $attr) { + //Add the classes we need during the compile phase, so that they stay + //even if something else like ngIf removes the element and re-addss it + $attr.$set('class', ($attr.class || '') + ' button icon button-icon', true); + return function($scope, $element, $attr, itemCtrl) { + var container = angular.element(ITEM_TPL_DELETE_BUTTON); + container.append($element); + itemCtrl.$element.append(container).addClass('item-left-editable'); + }; + } + }; +}]); diff --git a/js/angular/directive/itemOptionButton.js b/js/angular/directive/itemOptionButton.js new file mode 100644 index 0000000000..758ed19b9d --- /dev/null +++ b/js/angular/directive/itemOptionButton.js @@ -0,0 +1,47 @@ +var ITEM_TPL_OPTION_BUTTONS = + ''; +/** +* @ngdoc directive +* @name ionOptionButton +* @parent ionic.directive:ionItem +* @module ionic +* @restrict E +* Creates an option button inside a list item, that is visible when the item is swiped +* to the left by the user. Swiped open option buttons can be hidden with +* {@link ionic.directive:$ionicListDelegate#closeOptionButtons $ionicListDelegate#closeOptionButtons}. +* +* Can be assigned any button class. +* +* See {@link ionic.directive:ionList} for a complete example & explanation. +* +* @usage +* +* ```html +* +* +* I love kittens! +* Share +* Edit +* +* +* ``` +*/ +IonicModule +.directive('ionOptionButton', ['$compile', function($compile) { +return { + restrict: 'E', + require: '^ionItem', + priority: Number.MAX_VALUE, + compile: function($element, $attr) { + $attr.$set('class', ($attr.class || '') + ' button', true); + return function($scope, $element, $attr, itemCtrl) { + if (!itemCtrl.optionsContainer) { + itemCtrl.optionsContainer = angular.element(ITEM_TPL_OPTION_BUTTONS); + itemCtrl.$element.append(itemCtrl.optionsContainer); + } + itemCtrl.optionsContainer.append($element); + }; + } +}; +}]); diff --git a/js/angular/directive/itemReorderButton.js b/js/angular/directive/itemReorderButton.js new file mode 100644 index 0000000000..85ff338a31 --- /dev/null +++ b/js/angular/directive/itemReorderButton.js @@ -0,0 +1,71 @@ +var ITEM_TPL_REORDER_BUTTON = + '
' + + '
'; + +/** +* @ngdoc directive +* @name ionReorderButton +* @parent ionic.directive:ionItem +* @module ionic +* @restrict E +* Creates a reorder button inside a list item, that is visible when the +* {@link ionic.directive:ionList ionList parent's} `show-reorder` evaluates to true or +* `$ionicListDelegate.showReorder(true)` is called. +* +* 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). +* +* See {@link ionic.directive:ionList} for a complete example. +* +* @usage +* +* ```html +* +* +* Item {{$index}} +* +* +* +* +* ``` +* ```js +* function MyCtrl($scope) { +* $scope.items = [1, 2, 3, 4]; +* $scope.moveItem = function(item, fromIndex, toIndex) { +* //Move the item in the array +* $scope.items.splice(fromIndex, 1); +* $scope.items.splice(toIndex, 0, item); +* }; +* } +* ``` +* +* @param {expression=} on-reorder Expression to call when an item is reordered. +* Parameters given: $fromIndex, $toIndex. +*/ +IonicModule +.directive('ionReorderButton', [function() { + return { + restrict: 'E', + require: '^ionItem', + priority: Number.MAX_VALUE, + compile: function($element, $attr) { + $attr.$set('class', ($attr.class || '') + ' button icon button-icon', true); + $element[0].setAttribute('data-prevent-scroll', true); + return function($scope, $element, $attr, itemCtrl) { + $scope.$onReorder = function(oldIndex, newIndex) { + $scope.$eval($attr.onReorder, { + $fromIndex: oldIndex, + $toIndex: newIndex + }); + }; + + var container = angular.element(ITEM_TPL_REORDER_BUTTON); + container.append($element); + itemCtrl.$element.append(container).addClass('item-right-editable'); + }; + } + }; +}]); diff --git a/js/angular/directive/list.js b/js/angular/directive/list.js new file mode 100644 index 0000000000..1410639036 --- /dev/null +++ b/js/angular/directive/list.js @@ -0,0 +1,165 @@ +/** +* @ngdoc directive +* @name ionList +* @module ionic +* @delegate ionic.service:$ionicListDelegate +* @codepen JsHjf +* @restrict E +* @description +* The List is a widely used interface element in almost any mobile app, and can include +* content ranging from basic text all the way to buttons, toggles, icons, and thumbnails. +* +* Both the list, which contains items, and the list items themselves can be any HTML +* element. The containing element requires the `list` class and each list item requires +* the `item` class. +* +* However, using the ionList and ionItem directives make it easy to support various +* interaction modes such as swipe to edit, drag to reorder, and removing items. +* +* Related: {@link ionic.directive:ionItem}, {@link ionic.directive:ionOptionButton} +* {@link ionic.directive:ionReorderButton}, {@link ionic.directive:ionDeleteButton}, [`list CSS documentation`](/docs/components/#list). +* +* @usage +* +* Basic Usage: +* +* ```html +* +* +* {% raw %}Hello, {{item}}!{% endraw %} +* +* +* ``` +* +* Advanced Usage: Thumbnails, Delete buttons, Reordering, Swiping +* +* ```html +* +* +* +* {% raw %} +*

{{item.title}}

+*

{{item.description}}

{% endraw %} +* +* Share +* +* +* Edit +* +* +* +* +* +* +*
+*
+* ``` +* +* @param {string=} delegate-handle The handle used to identify this list with +* {@link ionic.service:$ionicListDelegate}. +* @param show-delete {boolean=} Whether the delete buttons for the items in the list are +* currently shown or hidden. +* @param show-reorder {boolean=} Whether the reorder buttons for the items in the list are +* currently shown or hidden. +* @param can-swipe {boolean=} Whether the items in the list are allowed to be swiped to reveal +* option buttons. Default: true. +*/ +IonicModule +.directive('ionList', [ +'$animate', +'$timeout', +function($animate, $timeout) { + return { + restrict: 'E', + require: ['ionList', '^?$ionicScroll'], + controller: '$ionicList', + compile: function($element, $attr) { + var listEl = angular.element('
') + .append( $element.contents() ); + $element.append(listEl); + + return function($scope, $element, $attrs, ctrls) { + var listCtrl = ctrls[0]; + var scrollCtrl = ctrls[1]; + + //Wait for child elements to render... + $timeout(init); + + function init() { + var listView = listCtrl.listView = new ionic.views.ListView({ + el: $element[0], + listEl: $element.children()[0], + scrollEl: scrollCtrl && scrollCtrl.element, + scrollView: scrollCtrl && scrollCtrl.scrollView, + onReorder: function(el, oldIndex, newIndex) { + var itemScope = angular.element(el).scope(); + if (itemScope && itemScope.$onReorder) { + itemScope.$onReorder(oldIndex, newIndex); + } + }, + canSwipe: function() { + return listCtrl.canSwipeItems(); + } + }); + + if (angular.isDefined($attr.canSwipe)) { + $scope.$watch('!!(' + $attr.canSwipe + ')', function(value) { + listCtrl.canSwipeItems(value); + }); + } + + if (angular.isDefined($attr.showDelete)) { + $scope.$watch('!!(' + $attr.showDelete + ')', function(value) { + listCtrl.showDelete(value); + }); + } + if (angular.isDefined($attr.showReorder)) { + $scope.$watch('!!(' + $attr.showReorder + ')', function(value) { + listCtrl.showReorder(value); + }); + } + + $scope.$watch(function() { + return listCtrl.showDelete(); + }, function(isShown, wasShown) { + //Only use isShown=false if it was already shown + if (!isShown && !wasShown) { return; } + + if (isShown) listCtrl.closeOptionButtons(); + + $element.children().toggleClass('list-left-editing', isShown); + toggleNgHide('.item-delete.item-left-edit', isShown); + }); + $scope.$watch(function() { + return listCtrl.showReorder(); + }, function(isShown, wasShown) { + //Only use isShown=false if it was already shown + if (!isShown && !wasShown) { return; } + + if (isShown) listCtrl.closeOptionButtons(); + listCtrl.showReorder(isShown); + + $element.children().toggleClass('list-right-editing', isShown); + toggleNgHide('.item-reorder.item-right-edit', isShown); + }); + + function toggleNgHide(selector, shouldShow) { + angular.forEach($element[0].querySelectorAll(selector), function(node) { + if (shouldShow) $animate.removeClass(angular.element(node), 'ng-hide'); + else $animate.addClass(angular.element(node), 'ng-hide'); + }); + } + } + + }; + } + }; +}]); diff --git a/js/angular/directive/menuClose.js b/js/angular/directive/menuClose.js new file mode 100644 index 0000000000..801ca34391 --- /dev/null +++ b/js/angular/directive/menuClose.js @@ -0,0 +1,29 @@ +/** + * @ngdoc directive + * @name menuClose + * @module ionic + * @restrict AC + * + * @description + * Closes a side menu which is currently opened. + * + * @usage + * Below is an example of a link within a side menu. Tapping this link would + * automatically close the currently opened menu + * + * ```html + * Home + * ``` + */ +IonicModule +.directive('menuClose', ['$ionicViewService', function($ionicViewService) { + return { + restrict: 'AC', + require: '^ionSideMenus', + link: function($scope, $element, $attr, sideMenuCtrl) { + $element.bind('click', function(){ + sideMenuCtrl.close(); + }); + } + }; +}]); diff --git a/js/angular/directive/menuToggle.js b/js/angular/directive/menuToggle.js new file mode 100644 index 0000000000..6ed0a0e38d --- /dev/null +++ b/js/angular/directive/menuToggle.js @@ -0,0 +1,40 @@ +/** + * @ngdoc directive + * @name menuToggle + * @module ionic + * @restrict AC + * + * @description + * Toggle a side menu on the given side + * + * @usage + * Below is an example of a link within a nav bar. Tapping this link would + * automatically open the given side menu + * + * ```html + * + * + * + * + * ... + * + * ``` + */ +IonicModule +.directive('menuToggle', ['$ionicViewService', function($ionicViewService) { + return { + restrict: 'AC', + require: '^ionSideMenus', + link: function($scope, $element, $attr, sideMenuCtrl) { + var side = $attr.menuToggle || 'left'; + $element.bind('click', function(){ + if(side === 'left') { + sideMenuCtrl.toggleLeft(); + } else if(side === 'right') { + sideMenuCtrl.toggleRight(); + } + }); + } + }; +}]) + diff --git a/js/ext/angular/src/directive/ionicModal.js b/js/angular/directive/modal.js similarity index 82% rename from js/ext/angular/src/directive/ionicModal.js rename to js/angular/directive/modal.js index ebfb8391f5..416eb570eb 100644 --- a/js/ext/angular/src/directive/ionicModal.js +++ b/js/angular/directive/modal.js @@ -1,12 +1,8 @@ -(function() { -'use strict'; - -angular.module('ionic.ui.modal', []) - /* * We don't document the ionModal directive, we instead document * the $ionicModal service */ +IonicModule .directive('ionModal', [function() { return { restrict: 'E', @@ -17,5 +13,3 @@ angular.module('ionic.ui.modal', []) '
' }; }]); - -})(); diff --git a/js/angular/directive/navBackButton.js b/js/angular/directive/navBackButton.js new file mode 100644 index 0000000000..267ebf5e43 --- /dev/null +++ b/js/angular/directive/navBackButton.js @@ -0,0 +1,98 @@ +/** + * @ngdoc directive + * @name ionNavBackButton + * @module ionic + * @restrict E + * @parent ionNavBar + * @description + * Creates a back button inside an {@link ionic.directive:ionNavBar}. + * + * Will show up when the user is able to go back in the current navigation stack. + * + * By default, will go back when clicked. If you wish for more advanced behavior, see the + * examples below. + * + * @usage + * + * With default click action: + * + * ```html + * + * + * Back! + * + * + * ``` + * + * With custom click action, using {@link ionic.service:$ionicNavBarDelegate}: + * + * ```html + * + * + * Back + * + * + * ``` + * ```js + * function MyCtrl($scope, $ionicNavBarDelegate) { + * $scope.goBack = function() { + * $ionicNavBarDelegate.back(); + * }; + * } + * ``` + * + * Displaying the previous title on the back button, again using + * {@link ionic.service:$ionicNavBarDelegate}. + * + * ```html + * + * + * {% raw %}{{getPreviousTitle() || 'Back'}}{% endraw %} + * + * + * ``` + * ```js + * function MyCtrl($scope, $ionicNavBarDelegate) { + * $scope.getPreviousTitle = function() { + * return $ionicNavBarDelegate.getPreviousTitle(); + * }; + * } + * ``` + */ +IonicModule +.directive('ionNavBackButton', [ + '$ionicNgClick', + '$animate', +function($ionicNgClick, $animate) { + return { + restrict: 'E', + require: '^ionNavBar', + compile: function(tElement, tAttrs) { + tElement.addClass('button back-button ng-hide'); + return function($scope, $element, $attr, navBarCtrl) { + if (!$attr.ngClick) { + $scope.$navBack = navBarCtrl.back; + $ionicNgClick($scope, $element, '$navBack($event)'); + } + + //If the current viewstate does not allow a back button, + //always hide it. + var deregisterListener = $scope.$parent.$on( + '$viewHistory.historyChange', + function(e, data) { + $scope.hasBackButton = !!data.showBack; + } + ); + $scope.$on('$destroy', deregisterListener); + + //Make sure both that a backButton is allowed in the first place, + //and that it is shown by the current view. + $scope.$watch('!!(backButtonShown && hasBackButton)', ionic.animationFrameThrottle(function(show) { + if (show) $animate.removeClass($element, 'ng-hide'); + else $animate.addClass($element, 'ng-hide'); + })); + }; + } + }; +}]); diff --git a/js/angular/directive/navBar.js b/js/angular/directive/navBar.js new file mode 100644 index 0000000000..92b7d61b34 --- /dev/null +++ b/js/angular/directive/navBar.js @@ -0,0 +1,93 @@ + +/** + * @ngdoc directive + * @name ionNavBar + * @module ionic + * @delegate ionic.service:$ionicNavBarDelegate + * @restrict E + * + * @description + * If we have an {@link ionic.directive:ionNavView} directive, we can also create an + * ``, which will create a topbar that updates as the application state changes. + * + * We can add a back button by putting an {@link ionic.directive:ionNavBackButton} inside. + * + * 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') + * + * @usage + * + * ```html + * + * + * + * + * + * + * + * + * ``` + * + * @param {string=} delegate-handle The handle used to identify this navBar + * with {@link ionic.service:$ionicNavBarDelegate}. + * @param align-title {string=} Where to align the title of the navbar. + * Available: 'left', 'right', 'center'. Defaults to 'center'. + */ +IonicModule +.directive('ionNavBar', [ + '$ionicViewService', + '$rootScope', + '$animate', + '$compile', +function($ionicViewService, $rootScope, $animate, $compile) { + + return { + restrict: 'E', + controller: '$ionicNavBar', + scope: true, + compile: function(tElement, tAttrs) { + //We cannot transclude here because it breaks element.data() inheritance on compile + tElement + .addClass('bar bar-header nav-bar') + .append( + '
' + + '
' + + '

' + + '
' + + '
' + ); + + return { pre: prelink }; + function prelink($scope, $element, $attr, navBarCtrl) { + navBarCtrl._headerBarView = new ionic.views.HeaderBar({ + el: $element[0], + alignTitle: $attr.alignTitle || 'center' + }); + + //defaults + $scope.backButtonShown = false; + $scope.shouldAnimate = true; + $scope.isReverse = false; + $scope.isInvisible = true; + + $scope.$on('$destroy', function() { + $scope.$parent.$hasHeader = false; + }); + + $scope.$watch(function() { + return ($scope.isReverse ? ' reverse' : '') + + ($scope.isInvisible ? ' invisible' : '') + + (!$scope.shouldAnimate ? ' no-animation' : ''); + }, function(className, oldClassName) { + $element.removeClass(oldClassName); + $element.addClass(className); + }); + + } + } + }; +}]); + diff --git a/js/angular/directive/navButtons.js b/js/angular/directive/navButtons.js new file mode 100644 index 0000000000..40e195b206 --- /dev/null +++ b/js/angular/directive/navButtons.js @@ -0,0 +1,74 @@ +/** + * @ngdoc directive + * @name ionNavButtons + * @module ionic + * @restrict E + * @parent ionNavView + * + * @description + * Use ionNavButtons to set the buttons on your {@link ionic.directive:ionNavBar} + * from within an {@link ionic.directive:ionView}. + * + * Any buttons you declare will be placed onto the navbar's corresponding side, + * and then destroyed when the user leaves their parent view. + * + * @usage + * ```html + * + * + * + * + * + * + * + * + * Some super content here! + * + * + * + * ``` + * + * @param {string} side The side to place the buttons on in the parent + * {@link ionic.directive:ionNavBar}. Available: 'left' or 'right'. + */ +IonicModule +.directive('ionNavButtons', ['$compile', '$animate', function($compile, $animate) { + return { + require: '^ionNavBar', + restrict: 'E', + compile: function($element, $attrs) { + var content = $element.contents().remove(); + return function($scope, $element, $attrs, navBarCtrl) { + var navElement = $attrs.side === 'right' ? + navBarCtrl.rightButtonsElement : + navBarCtrl.leftButtonsElement; + + //Put all of our inside buttons into their own span, + //so we can remove them all when this element dies - + //even if the buttons have changed through an ng-repeat or the like, + //we just remove their div parent and they are gone. + var buttons = angular.element('').append(content); + + //Compile buttons inside content so they have access to everything + //something inside content does (eg parent ionicScroll) + $element.append(buttons); + $compile(buttons)($scope); + + //Append buttons to navbar + $animate.enter(buttons, navElement); + + //When our ion-nav-buttons container is destroyed, + //destroy everything in the navbar + $scope.$on('$destroy', function() { + $animate.leave(buttons); + }); + + // The original element is just a completely empty element. + // make it invisible just to be sure it doesn't change any layout + $element.css('display', 'none'); + }; + } + }; +}]); diff --git a/js/angular/directive/navClear.js b/js/angular/directive/navClear.js new file mode 100644 index 0000000000..79588c0514 --- /dev/null +++ b/js/angular/directive/navClear.js @@ -0,0 +1,54 @@ + +/** + * @ngdoc directive + * @name navClear + * @module ionic + * @restrict AC + * + * @description + * Disables any transition animations between views, along with removing the back + * button which would normally show on the next view. This directive is useful for + * links within a sideMenu. + * + * @usage + * Below is an example of a link within a side menu. Tapping this link would disable + * any animations which would normally occur between views. + * + * ```html + * Home + * ``` + */ +IonicModule +.directive('navClear', [ + '$ionicViewService', + '$state', + '$location', + '$window', + '$rootScope', +function($ionicViewService, $location, $state, $window, $rootScope) { + $rootScope.$on('$stateChangeError', function() { + $ionicViewService.nextViewOptions(null); + }); + return { + priority: 100, + restrict: 'AC', + compile: function($element) { + return { pre: prelink }; + function prelink($scope, $element, $attrs) { + var unregisterListener; + function listenForStateChange() { + unregisterListener = $scope.$on('$stateChangeStart', function() { + $ionicViewService.nextViewOptions({ + disableAnimate: true, + disableBack: true + }); + unregisterListener(); + }); + $window.setTimeout(unregisterListener, 300); + } + + $element.on('click', listenForStateChange); + } + } + }; +}]); diff --git a/js/ext/angular/src/directive/ionicViewState.js b/js/angular/directive/navView.js similarity index 62% rename from js/ext/angular/src/directive/ionicViewState.js rename to js/angular/directive/navView.js index 4e48ac7c41..5b99343914 100644 --- a/js/ext/angular/src/directive/ionicViewState.js +++ b/js/angular/directive/navView.js @@ -1,84 +1,3 @@ -(function() { -'use strict'; - -angular.module('ionic.ui.viewState', ['ionic.service.view', 'ionic.service.gesture', 'ngSanitize']) - -/** - * @ngdoc directive - * @name ionView - * @module ionic - * @restrict E - * @parent ionNavView - * - * @description - * A container for content, used to tell a parent {@link ionic.directive:ionNavBar} - * about the current view. - * - * @usage - * Below is an example where our page will load with a navbar containing "My Page" as the title. - * - * ```html - * - * - * - * - * Hello! - * - * - * - * ``` - * - * @param {string=} title The title to display on the parent {@link ionic.directive:ionNavBar}. - * @param {boolean=} hideBackButton Whether to hide the back button on the parent - * {@link ionic.directive:ionNavBar} by default. - * @param {boolean=} hideNavBar Whether to hide the parent - * {@link ionic.directive:ionNavBar} by default. - */ -.directive('ionView', ['$ionicViewService', '$rootScope', '$animate', - function( $ionicViewService, $rootScope, $animate) { - return { - restrict: 'EA', - priority: 1000, - require: '^?ionNavBar', - compile: function(tElement, tAttrs, transclude) { - tElement.addClass('pane'); - tElement[0].removeAttribute('title'); - - return function link($scope, $element, $attr, navBarCtrl) { - if (!navBarCtrl) { - return; - } - - if (angular.isDefined($attr.title)) { - - var initialTitle = $attr.title; - navBarCtrl.changeTitle(initialTitle, $scope.$navDirection); - - // watch for changes in the title, don't set initial value as changeTitle does that - $attr.$observe('title', function(val, oldVal) { - if (val !== initialTitle) { - navBarCtrl.setTitle(val); - } - }); - - } - - $scope.$watch($attr.hideBackButton, function(value) { - // Should we hide a back button when this tab is shown - navBarCtrl.showBackButton(!value); - }); - - $scope.$watch($attr.hideNavBar, function(value) { - // Should the nav bar be hidden for this view or not? - navBarCtrl.showBar(!value); - }); - - }; - } - }; -}]) - - /** * @ngdoc directive * @name ionNavView @@ -172,8 +91,14 @@ angular.module('ionic.ui.viewState', ['ionic.service.view', 'ionic.service.gestu * same state. You can have views of the same name that live in different states. For more * information, see ui-router's [ui-view documentation](http://angular-ui.github.io/ui-router/site/#/api/ui.router.state.directive:ui-view). */ -.directive('ionNavView', ['$ionicViewService', '$state', '$compile', '$controller', '$animate', - function( $ionicViewService, $state, $compile, $controller, $animate) { +IonicModule +.directive('ionNavView', [ + '$ionicViewService', + '$state', + '$compile', + '$controller', + '$animate', +function( $ionicViewService, $state, $compile, $controller, $animate) { // IONIC's fork of Angular UI Router, v0.2.7 // the navView handles registering views in the history, which animation to use, and which var viewIsUpdating = false; @@ -183,14 +108,13 @@ angular.module('ionic.ui.viewState', ['ionic.service.view', 'ionic.service.gestu terminal: true, priority: 2000, transclude: true, - controller: [function(){ - }], + controller: function(){}, compile: function (element, attr, transclude) { return function(scope, element, attr, navViewCtrl) { var viewScope, viewLocals, - name = attr[directive.name] || attr.name || '', - onloadExp = attr.onload || '', - initialView = transclude(scope); + name = attr[directive.name] || attr.name || '', + onloadExp = attr.onload || '', + initialView = transclude(scope); // Put back the compiled initial view element.append(initialView); @@ -215,7 +139,7 @@ angular.module('ionic.ui.viewState', ['ionic.service.view', 'ionic.service.gestu }; scope.$on('$stateChangeSuccess', eventHook); - scope.$on('$viewContentLoading', eventHook); + // scope.$on('$viewContentLoading', eventHook); updateView(false); function updateView(doAnimate) { @@ -276,60 +200,5 @@ angular.module('ionic.ui.viewState', ['ionic.service.view', 'ionic.service.gestu } }; return directive; -}]) - - -/** - * @ngdoc directive - * @name navClear - * @module ionic - * @restrict AC - * - * @description - * Disables any transition animations between views, along with removing the back - * button which would normally show on the next view. This directive is useful for - * links within a sideMenu. - * - * @usage - * Below is an example of a link within a side menu. Tapping this link would disable - * any animations which would normally occur between views. - * - * ```html - * Home - * ``` - */ -.directive('navClear', [ - '$ionicViewService', - '$state', - '$location', - '$window', - '$rootScope', -function($ionicViewService, $location, $state, $window, $rootScope) { - $rootScope.$on('$stateChangeError', function() { - $ionicViewService.nextViewOptions(null); - }); - return { - priority: 100, - restrict: 'AC', - compile: function($element) { - return { pre: prelink }; - function prelink($scope, $element, $attrs) { - var unregisterListener; - function listenForStateChange() { - unregisterListener = $scope.$on('$stateChangeStart', function() { - $ionicViewService.nextViewOptions({ - disableAnimate: true, - disableBack: true - }); - unregisterListener(); - }); - $window.setTimeout(unregisterListener, 300); - } - - $element.on('click', listenForStateChange); - } - } - }; }]); -})(); diff --git a/js/angular/directive/ngClick.js b/js/angular/directive/ngClick.js new file mode 100644 index 0000000000..d1f63913b5 --- /dev/null +++ b/js/angular/directive/ngClick.js @@ -0,0 +1,59 @@ +// Similar to Angular's ngTouch, however it uses Ionic's tap detection +// and click simulation. ngClick + +IonicModule + +.config(['$provide', function($provide) { + $provide.decorator('ngClickDirective', ['$delegate', function($delegate) { + // drop the default ngClick directive + $delegate.shift(); + return $delegate; + }]); +}]) + +/** + * @private + */ +.factory('$ionicNgClick', ['$parse', function($parse) { + function onRelease(e) { + // wire this up to Ionic's tap/click simulation + ionic.tap.simulateClick(e.target, e); + } + return function(scope, element, clickExpr) { + var clickHandler = $parse(clickExpr); + + element.on('click', function(event) { + scope.$apply(function() { + clickHandler(scope, {$event: (event)}); + }); + }); + + ionic.on("release", onRelease, element[0]); + + // Hack for iOS Safari's benefit. It goes searching for onclick handlers and is liable to click + // something else nearby. + element.onclick = function(event) { }; + + scope.$on('$destroy', function () { + ionic.off("release", onRelease, element[0]); + }); + }; +}]) + +.directive('ngClick', ['$ionicNgClick', function($ionicNgClick) { + return function(scope, element, attr) { + $ionicNgClick(scope, element, attr.ngClick); + }; +}]) + +.directive('ionStopEvent', function () { + function stopEvent(e) { + e.stopPropagation(); + } + return { + restrict: 'A', + link: function (scope, element, attr) { + element.bind(attr.ionStopEvent, stopEvent); + } + }; +}); diff --git a/js/angular/directive/pane.js b/js/angular/directive/pane.js new file mode 100644 index 0000000000..119e865ac0 --- /dev/null +++ b/js/angular/directive/pane.js @@ -0,0 +1,18 @@ + +/** + * @ngdoc directive + * @name ionPane + * @module ionic + * @restrict E + * + * @description A simple container that fits content, with no side effects. Adds the 'pane' class to the element. + */ +IonicModule +.directive('ionPane', function() { + return { + restrict: 'E', + link: function(scope, element, attr) { + element.addClass('pane'); + } + }; +}); diff --git a/js/angular/directive/radio.js b/js/angular/directive/radio.js new file mode 100644 index 0000000000..fb7ee36bb1 --- /dev/null +++ b/js/angular/directive/radio.js @@ -0,0 +1,44 @@ +/** + * @ngdoc directive + * @name ionRadio + * @module ionic + * @restrict E + * @codepen saoBG + * @description + * The radio directive is no different than the HTML radio input, except it's styled differently. + * + * Radio behaves like any [AngularJS radio](http://docs.angularjs.org/api/ng/input/input[radio]). + * + * @usage + * ```html + * Choose A + * Choose B + * Choose C + * ``` + */ +IonicModule +.directive('ionRadio', function() { + return { + restrict: 'E', + replace: true, + require: '?ngModel', + scope: { + ngModel: '=?', + ngValue: '=?', + ngChange: '&', + icon: '@' + }, + transclude: true, + template: '', + + compile: function(element, attr) { + if(attr.name) element.children().eq(0).attr('name', attr.name); + if(attr.icon) element.children().eq(2).removeClass('ion-checkmark').addClass(attr.icon); + } + }; +}); diff --git a/js/angular/directive/refresher.js b/js/angular/directive/refresher.js new file mode 100644 index 0000000000..a82221ead5 --- /dev/null +++ b/js/angular/directive/refresher.js @@ -0,0 +1,100 @@ + +/** + * @ngdoc directive + * @name ionRefresher + * @module ionic + * @restrict E + * @parent ionic.directive:ionContent, ionic.directive:ionScroll + * @description + * Allows you to add pull-to-refresh to a scrollView. + * + * Place it as the first child of your {@link ionic.directive:ionContent} or + * {@link ionic.directive:ionScroll} element. + * + * When refreshing is complete, $broadcast the 'scroll.refreshComplete' event + * from your controller. + * + * @usage + * + * ```html + * + * + * + * + * + * + * + * ``` + * ```js + * angular.module('testApp', ['ionic']) + * .controller('MyController', function($scope, $http) { + * $scope.items = [1,2,3]; + * $scope.doRefresh = function() { + * $http.get('/new-items') + * .success(function(newItems) { + * $scope.items = newItems; + * }) + * .finally(function() { + * // Stop the ion-refresher from spinning + * $scope.$broadcast('scroll.refreshComplete'); + * }); + * }; + * }); + * ``` + * + * @param {expression=} on-refresh Called when the user pulls down enough and lets go + * of the refresher. + * @param {expression=} on-pulling Called when the user starts to pull down + * on the refresher. + * @param {string=} pulling-icon The icon to display while the user is pulling down. + * Default: 'ion-arrow-down-c'. + * @param {string=} pulling-text The text to display while the user is pulling down. + * @param {string=} refreshing-icon The icon to display after user lets go of the + * refresher. + * @param {string=} refreshing-text The text to display after the user lets go of + * the refresher. + * + */ +IonicModule +.directive('ionRefresher', ['$ionicBind', function($ionicBind) { + return { + restrict: 'E', + replace: true, + require: '^$ionicScroll', + template: + '
' + + '
' + + '' + + '
' + + '' + + '
' + + '
' + + '
', + compile: function($element, $attrs) { + if (angular.isUndefined($attrs.pullingIcon)) { + $attrs.$set('pullingIcon', 'ion-arrow-down-c'); + } + if (angular.isUndefined($attrs.refreshingIcon)) { + $attrs.$set('refreshingIcon', 'ion-loading-d'); + } + return function($scope, $element, $attrs, scrollCtrl) { + $ionicBind($scope, $attrs, { + pullingIcon: '@', + pullingText: '@', + refreshingIcon: '@', + refreshingText: '@', + $onRefresh: '&onRefresh', + $onPulling: '&onPulling' + }); + + scrollCtrl._setRefresher($scope, $element[0]); + $scope.$on('scroll.refreshComplete', function() { + $element[0].classList.remove('active'); + scrollCtrl.scrollView.finishPullToRefresh(); + }); + }; + } + }; +}]); diff --git a/js/ext/angular/src/directive/ionicScroll.js b/js/angular/directive/scroll.js similarity index 97% rename from js/ext/angular/src/directive/ionicScroll.js rename to js/angular/directive/scroll.js index 008e3c873f..9ad0ce4728 100644 --- a/js/ext/angular/src/directive/ionicScroll.js +++ b/js/angular/directive/scroll.js @@ -1,8 +1,3 @@ -(function() { -'use strict'; - -angular.module('ionic.ui.scroll', []) - /** * @ngdoc directive * @name ionScroll @@ -22,6 +17,7 @@ angular.module('ionic.ui.scroll', []) * @param {boolean=} scrollbar-x Whether to show the horizontal scrollbar. Default false. * @param {boolean=} scrollbar-y Whether to show the vertical scrollbar. Default true. */ +IonicModule .directive('ionScroll', [ '$timeout', '$controller', @@ -87,5 +83,3 @@ function($timeout, $controller, $ionicBind) { } }; }]); - -})(); diff --git a/js/angular/directive/sideMenu.js b/js/angular/directive/sideMenu.js new file mode 100644 index 0000000000..2b6a3a3608 --- /dev/null +++ b/js/angular/directive/sideMenu.js @@ -0,0 +1,59 @@ +/** + * @ngdoc directive + * @name ionSideMenu + * @module ionic + * @restrict E + * @parent ionic.directive:ionSideMenus + * + * @description + * A container for a side menu, sibling to an {@link ionic.directive:ionSideMenuContent} directive. + * + * @usage + * ```html + * + * + * ``` + * For a complete side menu example, see the + * {@link ionic.directive:ionSideMenus} documentation. + * + * @param {string} side Which side the side menu is currently on. Allowed values: 'left' or 'right'. + * @param {boolean=} is-enabled Whether this side menu is enabled. + * @param {number=} width How many pixels wide the side menu should be. Defaults to 275. + */ +IonicModule +.directive('ionSideMenu', function() { + return { + restrict: 'E', + require: '^ionSideMenus', + scope: true, + compile: function(element, attr) { + angular.isUndefined(attr.isEnabled) && attr.$set('isEnabled', 'true'); + angular.isUndefined(attr.width) && attr.$set('width', '275'); + + element.addClass('menu menu-' + attr.side); + + return function($scope, $element, $attr, sideMenuCtrl) { + $scope.side = $attr.side || 'left'; + + var sideMenu = sideMenuCtrl[$scope.side] = new ionic.views.SideMenu({ + width: 275, + el: $element[0], + isEnabled: true + }); + + $scope.$watch($attr.width, function(val) { + var numberVal = +val; + if (numberVal && numberVal == val) { + sideMenu.setWidth(+val); + } + }); + $scope.$watch($attr.isEnabled, function(val) { + sideMenu.setIsEnabled(!!val); + }); + }; + } + }; +}); diff --git a/js/angular/directive/sideMenuContent.js b/js/angular/directive/sideMenuContent.js new file mode 100644 index 0000000000..168d15cb5c --- /dev/null +++ b/js/angular/directive/sideMenuContent.js @@ -0,0 +1,125 @@ +/** + * @ngdoc directive + * @name ionSideMenuContent + * @module ionic + * @restrict E + * @parent ionic.directive:ionSideMenus + * + * @description + * A container for the main visible content, sibling to one or more + * {@link ionic.directive:ionSideMenu} directives. + * + * @usage + * ```html + * + * + * ``` + * For a complete side menu example, see the + * {@link ionic.directive:ionSideMenus} documentation. + * + * @param {boolean=} drag-content Whether the content can be dragged. Default true. + * + */ +IonicModule +.directive('ionSideMenuContent', [ + '$timeout', + '$ionicGesture', +function($timeout, $ionicGesture) { + + return { + restrict: 'EA', //DEPRECATED 'A' + require: '^ionSideMenus', + scope: true, + compile: function(element, attr) { + return { pre: prelink }; + function prelink($scope, $element, $attr, sideMenuCtrl) { + + $element.addClass('menu-content pane'); + + if (angular.isDefined(attr.dragContent)) { + $scope.$watch(attr.dragContent, function(value) { + sideMenuCtrl.canDragContent(value); + }); + } else { + sideMenuCtrl.canDragContent(true); + } + + var defaultPrevented = false; + var isDragging = false; + + // Listen for taps on the content to close the menu + function contentTap(e) { + if(sideMenuCtrl.getOpenAmount() !== 0) { + sideMenuCtrl.close(); + e.gesture.srcEvent.preventDefault(); + } + } + ionic.on('tap', contentTap, $element[0]); + + var dragFn = function(e) { + if(defaultPrevented || !sideMenuCtrl.isDraggableTarget(e)) return; + isDragging = true; + sideMenuCtrl._handleDrag(e); + e.gesture.srcEvent.preventDefault(); + }; + + var dragVertFn = function(e) { + if(isDragging) { + e.gesture.srcEvent.preventDefault(); + } + }; + + //var dragGesture = Gesture.on('drag', dragFn, $element); + var dragRightGesture = $ionicGesture.on('dragright', dragFn, $element); + var dragLeftGesture = $ionicGesture.on('dragleft', dragFn, $element); + var dragUpGesture = $ionicGesture.on('dragup', dragVertFn, $element); + var dragDownGesture = $ionicGesture.on('dragdown', dragVertFn, $element); + + var dragReleaseFn = function(e) { + isDragging = false; + if(!defaultPrevented) { + sideMenuCtrl._endDrag(e); + } + defaultPrevented = false; + }; + + var releaseGesture = $ionicGesture.on('release', dragReleaseFn, $element); + + sideMenuCtrl.setContent({ + onDrag: function(e) {}, + endDrag: function(e) {}, + getTranslateX: function() { + return $scope.sideMenuContentTranslateX || 0; + }, + setTranslateX: ionic.animationFrameThrottle(function(amount) { + $element[0].style[ionic.CSS.TRANSFORM] = 'translate3d(' + amount + 'px, 0, 0)'; + $timeout(function() { + $scope.sideMenuContentTranslateX = amount; + }); + }), + enableAnimation: function() { + //this.el.classList.add(this.animateClass); + $scope.animationEnabled = true; + $element[0].classList.add('menu-animated'); + }, + disableAnimation: function() { + //this.el.classList.remove(this.animateClass); + $scope.animationEnabled = false; + $element[0].classList.remove('menu-animated'); + } + }); + + // Cleanup + $scope.$on('$destroy', function() { + $ionicGesture.off(dragLeftGesture, 'dragleft', dragFn); + $ionicGesture.off(dragRightGesture, 'dragright', dragFn); + $ionicGesture.off(dragUpGesture, 'dragup', dragFn); + $ionicGesture.off(dragDownGesture, 'dragdown', dragFn); + $ionicGesture.off(releaseGesture, 'release', dragReleaseFn); + ionic.off('tap', contentTap, $element[0]); + }); + } + } + }; +}]); diff --git a/js/angular/directive/sideMenus.js b/js/angular/directive/sideMenus.js new file mode 100644 index 0000000000..bee5470534 --- /dev/null +++ b/js/angular/directive/sideMenus.js @@ -0,0 +1,61 @@ +IonicModule + +/** + * @ngdoc directive + * @name ionSideMenus + * @module ionic + * @delegate ionic.service:$ionicSideMenuDelegate + * @restrict E + * + * @description + * A container element for side menu(s) and the main content. Allows the left + * and/or right side menu to be toggled by dragging the main content area side + * to side. + * + * ![Side Menu](http://ionicframework.com.s3.amazonaws.com/docs/controllers/sidemenu.gif) + * + * For more information on side menus, check out the documenation for + * {@link ionic.directive:ionSideMenuContent} and + * {@link ionic.directive:ionSideMenu}. + * + * @usage + * To use side menus, add an `` parent element, + * an `` for the center content, + * and one or more `` directives. + * + * ```html + * + * + * + * + * + * + * + * + * + * + * + * + * + * ``` + * ```js + * function ContentController($scope, $ionicSideMenuDelegate) { + * $scope.toggleLeft = function() { + * $ionicSideMenuDelegate.toggleLeft(); + * }; + * } + * ``` + * + * @param {string=} delegate-handle The handle used to identify this side menu + * with {@link ionic.service:$ionicSideMenuDelegate}. + * + */ +.directive('ionSideMenus', [function() { + return { + restrict: 'ECA', + replace: true, + transclude: true, + controller: '$ionicSideMenus', + template: '
' + }; +}]); diff --git a/js/ext/angular/src/directive/ionicSlideBox.js b/js/angular/directive/slideBox.js similarity index 67% rename from js/ext/angular/src/directive/ionicSlideBox.js rename to js/angular/directive/slideBox.js index 88a04e3fdf..c30dea308d 100644 --- a/js/ext/angular/src/directive/ionicSlideBox.js +++ b/js/angular/directive/slideBox.js @@ -1,107 +1,3 @@ -(function() { -'use strict'; - -angular.module('ionic.ui.slideBox', []) - -/** - * @ngdoc service - * @name $ionicSlideBoxDelegate - * @module ionic - * @description - * Delegate that controls the {@link ionic.directive:ionSlideBox} directive. - * - * Methods called directly on the $ionicSlideBoxDelegate service will control all side - * menus. Use the {@link ionic.service:$ionicSlideBoxDelegate#$getByHandle $getByHandle} - * method to control specific slide box instances. - * - * @usage - * - * ```html - * - * - * - *
- * - *
- *
- * - *
- * Slide 2! - *
- *
- *
- * - * ``` - * ```js - * function MyCtrl($scope, $ionicSlideBoxDelegate) { - * $scope.nextSlide = function() { - * $ionicSlideBoxDelegate.next(); - * } - * } - * ``` - */ -.service('$ionicSlideBoxDelegate', delegateService([ - /** - * @ngdoc method - * @name $ionicSlideBoxDelegate#update - * @description - * Update the slidebox (for example if using Angular with ng-repeat, - * resize it for the elements inside). - */ - 'update', - /** - * @ngdoc method - * @name $ionicSlideBoxDelegate#slide - * @param {number} to The index to slide to. - * @param {number=} speed The number of milliseconds for the change to take. - */ - 'slide', - /** - * @ngdoc method - * @name $ionicSlideBoxDelegate#previous - * @description Go to the previous slide. Wraps around if at the beginning. - */ - 'previous', - /** - * @ngdoc method - * @name $ionicSlideBoxDelegate#next - * @description Go to the next slide. Wraps around if at the end. - */ - 'next', - /** - * @ngdoc method - * @name $ionicSlideBoxDelegate#stop - * @description Stop sliding. The slideBox will not move again until - * explicitly told to do so. - */ - 'stop', - /** - * @ngdoc method - * @name $ionicSlideBoxDelegate#currentIndex - * @returns number The index of the current slide. - */ - 'currentIndex', - /** - * @ngdoc method - * @name $ionicSlideBoxDelegate#slidesCount - * @returns number The number of slides there are currently. - */ - 'slidesCount' - /** - * @ngdoc method - * @name $ionicSlideBoxDelegate#$getByHandle - * @param {string} handle - * @returns `delegateInstance` A delegate instance that controls only the - * {@link ionic.directive:ionSlideBox} directives with `delegate-handle` matching - * the given handle. - * - * Example: `$ionicSlideBoxDelegate.$getByHandle('my-handle').stop();` - */ -])) - -/** - * The internal controller for the slide box controller. - */ /** * @ngdoc directive @@ -139,6 +35,7 @@ angular.module('ionic.ui.slideBox', []) * @param {expression=} on-slide-changed Expression called whenever the slide is changed. Is passed an 'index' variable. * @param {expression=} active-slide Model to bind the current slide to. */ +IonicModule .directive('ionSlideBox', [ '$timeout', '$compile', @@ -238,7 +135,6 @@ function($timeout, $compile, $ionicSlideBoxDelegate) { } }; }]) - .directive('ionSlide', function() { return { restrict: 'E', @@ -285,5 +181,3 @@ function($timeout, $compile, $ionicSlideBoxDelegate) { }; }); - -})(); diff --git a/js/angular/directive/tab.js b/js/angular/directive/tab.js new file mode 100644 index 0000000000..bc01d983a7 --- /dev/null +++ b/js/angular/directive/tab.js @@ -0,0 +1,136 @@ +/** + * @ngdoc directive + * @name ionTab + * @module ionic + * @restrict E + * @parent ionic.directive:ionTabs + * + * @description + * Contains a tab's content. The content only exists while the given tab is selected. + * + * Each ionTab has its own view history. + * + * @usage + * ```html + * + * + * ``` + * For a complete, working tab bar example, see the {@link ionic.directive:ionTabs} documentation. + * + * @param {string} title The title of the tab. + * @param {string=} href The link that this tab will navigate to when tapped. + * @param {string=} icon The icon of the tab. If given, this will become the default for icon-on and icon-off. + * @param {string=} icon-on The icon of the tab while it is selected. + * @param {string=} icon-off The icon of the tab while it is not selected. + * @param {expression=} badge The badge to put on this tab (usually a number). + * @param {expression=} badge-style The style of badge to put on this tab (eg tabs-positive). + * @param {expression=} on-select Called when this tab is selected. + * @param {expression=} on-deselect Called when this tab is deselected. + * @param {expression=} ng-click By default, the tab will be selected on click. If ngClick is set, it will not. You can explicitly switch tabs using {@link ionic.service:$ionicTabsDelegate#select $ionicTabsDelegate.select()}. + */ +IonicModule +.directive('ionTab', [ + '$rootScope', + '$animate', + '$ionicBind', + '$compile', +function($rootScope, $animate, $ionicBind, $compile) { + + //Returns ' key="value"' if value exists + function attrStr(k,v) { + return angular.isDefined(v) ? ' ' + k + '="' + v + '"' : ''; + } + return { + restrict: 'E', + require: ['^ionTabs', 'ionTab'], + replace: true, + controller: '$ionicTab', + scope: true, + compile: function(element, attr) { + var navView = element[0].querySelector('ion-nav-view') || + element[0].querySelector('data-ion-nav-view'); + var navViewName = navView && navView.getAttribute('name'); + + + //We create the tabNavElement in the compile phase so that the + //attributes we pass down won't be interpolated yet - we want + //to pass down the 'raw' versions of the attributes + var tabNavElement = angular.element( + '' + ); + + //Remove the contents of the element so we can compile them later, if tab is selected + //We don't use regular transclusion because it breaks element inheritance + var tabContent = angular.element('
') + .append( element.contents().remove() ); + + return function link($scope, $element, $attr, ctrls) { + var childScope; + var childElement; + var tabsCtrl = ctrls[0]; + var tabCtrl = ctrls[1]; + + $ionicBind($scope, $attr, { + animate: '=', + onSelect: '&', + onDeselect: '&', + title: '@', + uiSref: '@', + href: '@', + }); + + tabsCtrl.add($scope); + $scope.$on('$destroy', function() { + tabsCtrl.remove($scope); + tabNavElement.isolateScope().$destroy(); + tabNavElement.remove(); + }); + + //Remove title attribute so browser-tooltip does not apear + $element[0].removeAttribute('title'); + + if (navViewName) { + tabCtrl.navViewName = navViewName; + } + $scope.$on('$stateChangeSuccess', selectIfMatchesState); + selectIfMatchesState(); + function selectIfMatchesState() { + if (tabCtrl.tabMatchesState()) { + tabsCtrl.select($scope); + } + } + + tabNavElement.data('$ionTabsController', tabsCtrl); + tabNavElement.data('$ionTabController', tabCtrl); + tabsCtrl.$tabsElement.append($compile(tabNavElement)($scope)); + + $scope.$watch('$tabSelected', function(value) { + childScope && childScope.$destroy(); + childScope = null; + childElement && $animate.leave(childElement); + childElement = null; + if (value) { + childScope = $scope.$new(); + childElement = tabContent.clone(); + $animate.enter(childElement, tabsCtrl.$element); + $compile(childElement)(childScope); + } + }); + + }; + } + }; +}]); diff --git a/js/angular/directive/tabNav.js b/js/angular/directive/tabNav.js new file mode 100644 index 0000000000..c80792e583 --- /dev/null +++ b/js/angular/directive/tabNav.js @@ -0,0 +1,52 @@ +IonicModule +.directive('ionTabNav', ['$ionicNgClick', function($ionicNgClick) { + return { + restrict: 'E', + replace: true, + require: ['^ionTabs', '^ionTab'], + template: + '' + + '{{badge}}' + + '' + + '' + + '' + + '', + scope: { + title: '@', + icon: '@', + iconOn: '@', + iconOff: '@', + badge: '=', + badgeStyle: '@' + }, + compile: function(element, attr, transclude) { + return function link($scope, $element, $attrs, ctrls) { + var tabsCtrl = ctrls[0], + tabCtrl = ctrls[1]; + + //Remove title attribute so browser-tooltip does not apear + $element[0].removeAttribute('title'); + + $scope.selectTab = function(e) { + e.preventDefault(); + tabsCtrl.select(tabCtrl.$scope, true); + }; + if (!$attrs.ngClick) { + $ionicNgClick($scope, $element, 'selectTab($event)'); + } + + $scope.getIconOn = function() { + return $scope.iconOn || $scope.icon; + }; + $scope.getIconOff = function() { + return $scope.iconOff || $scope.icon; + }; + + $scope.isTabActive = function() { + return tabsCtrl.selectedTab() === tabCtrl.$scope; + }; + }; + } + }; +}]); diff --git a/js/angular/directive/tabs.js b/js/angular/directive/tabs.js new file mode 100644 index 0000000000..67c354be13 --- /dev/null +++ b/js/angular/directive/tabs.js @@ -0,0 +1,83 @@ + +/** + * @ngdoc directive + * @name ionTabs + * @module ionic + * @delegate ionic.service:$ionicTabsDelegate + * @restrict E + * @codepen KbrzJ + * + * @description + * Powers a multi-tabbed interface with a Tab Bar and a set of "pages" that can be tabbed + * through. + * + * Assign any [tabs class](/docs/components#tabs) or + * [animation class](/docs/components#animation) to the element to define + * its look and feel. + * + * See the {@link ionic.directive:ionTab} directive's documentation for more details on + * individual tabs. + * + * @usage + * ```html + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * ``` + * + * @param {string=} delegate-handle The handle used to identify these tabs + * with {@link ionic.service:$ionicTabsDelegate}. + */ +IonicModule + +.directive('ionTabs', ['$ionicViewService', '$ionicTabsDelegate', function($ionicViewService, $ionicTabsDelegate) { + return { + restrict: 'E', + scope: true, + controller: '$ionicTabs', + compile: function(element, attr) { + element.addClass('view'); + //We cannot use regular transclude here because it breaks element.data() + //inheritance on compile + var innerElement = angular.element('
'); + innerElement.append(element.contents()); + element.append(innerElement); + + return { pre: prelink }; + function prelink($scope, $element, $attr, tabsCtrl) { + var deregisterInstance = $ionicTabsDelegate._registerInstance( + tabsCtrl, $attr.delegateHandle + ); + + $scope.$on('$destroy', deregisterInstance); + + tabsCtrl.$scope = $scope; + tabsCtrl.$element = $element; + tabsCtrl.$tabsElement = angular.element($element[0].querySelector('.tabs')); + + var el = $element[0]; + $scope.$watch(function() { return el.className; }, function(value) { + var isTabsTop = value.indexOf('tabs-top') !== -1; + var isHidden = value.indexOf('tabs-item-hide') !== -1; + $scope.$hasTabs = !isTabsTop && !isHidden; + $scope.$hasTabsTop = isTabsTop && !isHidden; + }); + $scope.$on('$destroy', function() { + $scope.$hasTabs = $scope.$hasTabsTop = null; + }); + } + } + }; +}]); diff --git a/js/ext/angular/src/directive/ionicToggle.js b/js/angular/directive/toggle.js similarity index 92% rename from js/ext/angular/src/directive/ionicToggle.js rename to js/angular/directive/toggle.js index 35d343f7be..d6d683cfab 100644 --- a/js/ext/angular/src/directive/ionicToggle.js +++ b/js/angular/directive/toggle.js @@ -1,8 +1,3 @@ -(function(ionic) { -'use strict'; - -angular.module('ionic.ui.toggle', []) - /** * @ngdoc directive * @name ionToggle @@ -18,7 +13,11 @@ angular.module('ionic.ui.toggle', []) * The toggle behaves like any [AngularJS checkbox](http://docs.angularjs.org/api/ng/input/input[checkbox]) otherwise. * */ -.directive('ionToggle', ['$ionicGesture', '$timeout', function($ionicGesture, $timeout) { +IonicModule +.directive('ionToggle', [ + '$ionicGesture', + '$timeout', +function($ionicGesture, $timeout) { return { restrict: 'E', @@ -82,5 +81,3 @@ angular.module('ionic.ui.toggle', []) }; }]); - -})(window.ionic); diff --git a/js/ext/angular/src/directive/ionicTouch.js b/js/angular/directive/touch.js similarity index 100% rename from js/ext/angular/src/directive/ionicTouch.js rename to js/angular/directive/touch.js diff --git a/js/angular/directive/view.js b/js/angular/directive/view.js new file mode 100644 index 0000000000..7721c54b4e --- /dev/null +++ b/js/angular/directive/view.js @@ -0,0 +1,75 @@ +/** + * @ngdoc directive + * @name ionView + * @module ionic + * @restrict E + * @parent ionNavView + * + * @description + * A container for content, used to tell a parent {@link ionic.directive:ionNavBar} + * about the current view. + * + * @usage + * Below is an example where our page will load with a navbar containing "My Page" as the title. + * + * ```html + * + * + * + * + * Hello! + * + * + * + * ``` + * + * @param {string=} title The title to display on the parent {@link ionic.directive:ionNavBar}. + * @param {boolean=} hideBackButton Whether to hide the back button on the parent + * {@link ionic.directive:ionNavBar} by default. + * @param {boolean=} hideNavBar Whether to hide the parent + * {@link ionic.directive:ionNavBar} by default. + */ +IonicModule +.directive('ionView', ['$ionicViewService', '$rootScope', '$animate', + function( $ionicViewService, $rootScope, $animate) { + return { + restrict: 'EA', + priority: 1000, + require: '^?ionNavBar', + compile: function(tElement, tAttrs, transclude) { + tElement.addClass('pane'); + tElement[0].removeAttribute('title'); + + return function link($scope, $element, $attr, navBarCtrl) { + if (!navBarCtrl) { + return; + } + + if (angular.isDefined($attr.title)) { + + var initialTitle = $attr.title; + navBarCtrl.changeTitle(initialTitle, $scope.$navDirection); + + // watch for changes in the title, don't set initial value as changeTitle does that + $attr.$observe('title', function(val, oldVal) { + if (val !== initialTitle) { + navBarCtrl.setTitle(val); + } + }); + + } + + $scope.$watch($attr.hideBackButton, function(value) { + // Should we hide a back button when this tab is shown + navBarCtrl.showBackButton(!value); + }); + + $scope.$watch($attr.hideNavBar, function(value) { + // Should the nav bar be hidden for this view or not? + navBarCtrl.showBar(!value); + }); + + }; + } + }; +}]); diff --git a/js/angular/main.js b/js/angular/main.js new file mode 100644 index 0000000000..0932ee66c3 --- /dev/null +++ b/js/angular/main.js @@ -0,0 +1,10 @@ +/** + * Create a wrapping module to ease having to include too many + * modules. + */ +var IonicModule = angular.module('ionic', [ + // Angular deps + 'ngAnimate', + 'ngSanitize', + 'ui.router' +]); diff --git a/js/ext/angular/src/service/ionicActionSheet.js b/js/angular/service/actionSheet.js similarity index 94% rename from js/ext/angular/src/service/ionicActionSheet.js rename to js/angular/service/actionSheet.js index 2ea1350cfe..5ed61d8ead 100644 --- a/js/ext/angular/src/service/ionicActionSheet.js +++ b/js/angular/service/actionSheet.js @@ -1,5 +1,3 @@ -angular.module('ionic.service.actionSheet', ['ionic.service.templateLoad', 'ionic.service.platform', 'ionic.ui.actionSheet', 'ngAnimate']) - /** * @ngdoc service * @name $ionicActionSheet @@ -42,7 +40,15 @@ angular.module('ionic.service.actionSheet', ['ionic.service.templateLoad', 'ioni * ``` * */ -.factory('$ionicActionSheet', ['$rootScope', '$document', '$compile', '$animate', '$timeout', '$ionicTemplateLoader', '$ionicPlatform', +IonicModule +.factory('$ionicActionSheet', [ + '$rootScope', + '$document', + '$compile', + '$animate', + '$timeout', + '$ionicTemplateLoader', + '$ionicPlatform', function($rootScope, $document, $compile, $animate, $timeout, $ionicTemplateLoader, $ionicPlatform) { return { diff --git a/js/ext/angular/src/service/angularOverrides.js b/js/angular/service/angularOverrides.js similarity index 100% rename from js/ext/angular/src/service/angularOverrides.js rename to js/angular/service/angularOverrides.js diff --git a/js/ext/angular/src/service/ionicBackdrop.js b/js/angular/service/backdrop.js similarity index 97% rename from js/ext/angular/src/service/ionicBackdrop.js rename to js/angular/service/backdrop.js index c9c3b6d6c5..25e35c4436 100644 --- a/js/ext/angular/src/service/ionicBackdrop.js +++ b/js/angular/service/backdrop.js @@ -1,5 +1,3 @@ -angular.module('ionic') - /** * @ngdoc service * @name $ionicBackdrop @@ -17,7 +15,7 @@ angular.module('ionic') * * For each time `retain` is called, the backdrop will be shown until `release` is called. * - * For example, if `retain` is called three times, the backdrop will be shown until `release` + * For example, if `retain` is called three times, the backdrop will be shown until `release` * is called three times. * * @usage @@ -34,6 +32,7 @@ angular.module('ionic') * } * ``` */ +IonicModule .factory('$ionicBackdrop', [ '$document', function($document) { diff --git a/js/ext/angular/src/service/ionicBind.js b/js/angular/service/bind.js similarity index 97% rename from js/ext/angular/src/service/ionicBind.js rename to js/angular/service/bind.js index f76eb8f81d..6e90f9ff2f 100644 --- a/js/ext/angular/src/service/ionicBind.js +++ b/js/angular/service/bind.js @@ -1,7 +1,7 @@ -angular.module('ionic.service.bind', []) /** * @private */ +IonicModule .factory('$ionicBind', ['$parse', '$interpolate', function($parse, $interpolate) { var LOCAL_REGEXP = /^\s*([@=&])(\??)\s*(\w*)\s*$/; return function(scope, attrs, bindDefinition) { diff --git a/js/ext/angular/src/service/decorators/location.js b/js/angular/service/decorators/location.js similarity index 88% rename from js/ext/angular/src/service/decorators/location.js rename to js/angular/service/decorators/location.js index 53d25acc53..58887d2dc5 100644 --- a/js/ext/angular/src/service/decorators/location.js +++ b/js/angular/service/decorators/location.js @@ -1,9 +1,9 @@ -angular.module('ionic.decorator.location', []) - /** * @private */ -.config(['$provide', function($provide) { +IonicModule.config([ + '$provide', +function($provide) { function $LocationDecorator($location, $timeout) { $location.__hash = $location.hash; @@ -23,6 +23,6 @@ angular.module('ionic.decorator.location', []) return $location; } - + $provide.decorator('$location', ['$delegate', '$timeout', $LocationDecorator]); }]); diff --git a/js/ext/angular/src/service/delegateService.js b/js/angular/service/delegateService.js similarity index 100% rename from js/ext/angular/src/service/delegateService.js rename to js/angular/service/delegateService.js diff --git a/js/ext/angular/src/service/ionicGesture.js b/js/angular/service/gesture.js similarity index 96% rename from js/ext/angular/src/service/ionicGesture.js rename to js/angular/service/gesture.js index b2abe42c92..4566034b62 100644 --- a/js/ext/angular/src/service/ionicGesture.js +++ b/js/angular/service/gesture.js @@ -1,5 +1,3 @@ -angular.module('ionic.service.gesture', []) - /** * @ngdoc service * @name $ionicGesture @@ -7,6 +5,7 @@ angular.module('ionic.service.gesture', []) * @description An angular service exposing ionic * {@link ionic.utility:ionic.EventController}'s gestures. */ +IonicModule .factory('$ionicGesture', [function() { return { /** diff --git a/js/ext/angular/src/service/ionicLoading.js b/js/angular/service/loading.js similarity index 89% rename from js/ext/angular/src/service/ionicLoading.js rename to js/angular/service/loading.js index 34bd4a3768..f07adbb64e 100644 --- a/js/ext/angular/src/service/ionicLoading.js +++ b/js/angular/service/loading.js @@ -1,13 +1,11 @@ -var TPL_LOADING = +var LOADING_TPL = '
' + '
'; -var HIDE_LOADING_DEPRECATED = '$ionicLoading instance.hide() has been deprecated. Use $ionicLoading.hide().'; -var SHOW_LOADING_DEPRECATED = '$ionicLoading instance.show() has been deprecated. Use $ionicLoading.show().'; -var SET_LOADING_DEPRECATED = '$ionicLoading instance.setContent() has been deprecated. Use $ionicLoading.show({ template: \'my content\' }).'; - -angular.module('ionic.service.loading', []) +var LOADING_HIDE_DEPRECATED = '$ionicLoading instance.hide() has been deprecated. Use $ionicLoading.hide().'; +var LOADING_SHOW_DEPRECATED = '$ionicLoading instance.show() has been deprecated. Use $ionicLoading.show().'; +var LOADING_SET_DEPRECATED = '$ionicLoading instance.setContent() has been deprecated. Use $ionicLoading.show({ template: \'my content\' }).'; /** * @ngdoc service @@ -32,6 +30,7 @@ angular.module('ionic.service.loading', []) * }); * ``` */ +IonicModule .factory('$ionicLoading', [ '$document', '$ionicTemplateLoader', @@ -57,7 +56,7 @@ function($document, $ionicTemplateLoader, $ionicBackdrop, $timeout, $q, $log, $c * - `{string=}` `templateUrl` The url of an html template to load as the content of the indicator. * - `{boolean=}` `noBackdrop` Whether to hide the backdrop. * - `{number=}` `delay` How many milliseconds to delay showing the indicator. - * - `{number=} `duration` How many milliseconds to wait until automatically + * - `{number=}` `duration` How many milliseconds to wait until automatically * hiding the indicator. */ show: showLoader, @@ -76,7 +75,7 @@ function($document, $ionicTemplateLoader, $ionicBackdrop, $timeout, $q, $log, $c function getLoader() { if (!loaderInstance) { loaderInstance = $ionicTemplateLoader.compile({ - template: TPL_LOADING, + template: LOADING_TPL, appendTo: $document[0].body }) .then(function(loader) { @@ -152,11 +151,11 @@ function($document, $ionicTemplateLoader, $ionicBackdrop, $timeout, $q, $log, $c }); return { - hide: deprecated.method(HIDE_LOADING_DEPRECATED, $log.error, hideLoader), - show: deprecated.method(SHOW_LOADING_DEPRECATED, $log.error, function() { + hide: deprecated.method(LOADING_HIDE_DEPRECATED, $log.error, hideLoader), + show: deprecated.method(LOADING_SHOW_DEPRECATED, $log.error, function() { showLoader(options); }), - setContent: deprecated.method(SET_LOADING_DEPRECATED, $log.error, function(content) { + setContent: deprecated.method(LOADING_SET_DEPRECATED, $log.error, function(content) { getLoader().then(function(loader) { loader.show({ template: content }); }); diff --git a/js/ext/angular/src/service/ionicModal.js b/js/angular/service/modal.js similarity index 98% rename from js/ext/angular/src/service/ionicModal.js rename to js/angular/service/modal.js index 4bb5d5ebed..1c353a43d3 100644 --- a/js/ext/angular/src/service/ionicModal.js +++ b/js/angular/service/modal.js @@ -1,5 +1,3 @@ -angular.module('ionic.service.modal', ['ionic.service.templateLoad', 'ionic.service.platform', 'ionic.ui.modal']) - /** * @ngdoc service * @name $ionicModal @@ -43,6 +41,7 @@ angular.module('ionic.service.modal', ['ionic.service.templateLoad', 'ionic.serv * }); * ``` */ +IonicModule .factory('$ionicModal', [ '$rootScope', '$document', @@ -105,7 +104,6 @@ function($rootScope, $document, $compile, $timeout, $ionicPlatform, $ionicTempla modalEl.addClass('ng-enter active') .removeClass('ng-leave ng-leave-active'); - self._isShown = true; self._deregisterBackButton = $ionicPlatform.registerBackButtonAction(function(){ self.hide(); @@ -161,7 +159,7 @@ function($rootScope, $document, $compile, $timeout, $ionicPlatform, $ionicTempla */ remove: function() { var self = this; - self.scope.$parent && self.scope.$parent.$broadcast('modal.removed'); + self.scope.$parent && self.scope.$parent.$broadcast('modal.removed', self); return self.hide().then(function() { self.scope.$destroy(); diff --git a/js/angular/service/navBarDelegate.js b/js/angular/service/navBarDelegate.js new file mode 100644 index 0000000000..1acd18cc09 --- /dev/null +++ b/js/angular/service/navBarDelegate.js @@ -0,0 +1,103 @@ + +/** + * @ngdoc service + * @name $ionicNavBarDelegate + * @module ionic + * @description + * Delegate for controlling the {@link ionic.directive:ionNavBar} directive. + * + * @usage + * + * ```html + * + * + * + * + * + * ``` + * ```js + * function MyCtrl($scope, $ionicNavBarDelegate) { + * $scope.setNavTitle = function(title) { + * $ionicNavBarDelegate.setTitle(title); + * } + * } + * ``` + */ +IonicModule +.service('$ionicNavBarDelegate', delegateService([ + /** + * @ngdoc method + * @name $ionicNavBarDelegate#back + * @description Goes back in the view history. + * @param {DOMEvent=} event The event object (eg from a tap event) + */ + 'back', + /** + * @ngdoc method + * @name $ionicNavBarDelegate#align + * @description Aligns the title with the buttons in a given direction. + * @param {string=} direction The direction to the align the title text towards. + * Available: 'left', 'right', 'center'. Default: 'center'. + */ + 'align', + /** + * @ngdoc method + * @name $ionicNavBarDelegate#showBackButton + * @description + * Set/get whether the {@link ionic.directive:ionNavBackButton} is shown + * (if it exists). + * @param {boolean=} show Whether to show the back button. + * @returns {boolean} Whether the back button is shown. + */ + 'showBackButton', + /** + * @ngdoc method + * @name $ionicNavBarDelegate#showBar + * @description + * Set/get whether the {@link ionic.directive:ionNavBar} is shown. + * @param {boolean} show Whether to show the bar. + * @returns {boolean} Whether the bar is shown. + */ + 'showBar', + /** + * @ngdoc method + * @name $ionicNavBarDelegate#setTitle + * @description + * Set the title for the {@link ionic.directive:ionNavBar}. + * @param {string} title The new title to show. + */ + 'setTitle', + /** + * @ngdoc method + * @name $ionicNavBarDelegate#changeTitle + * @description + * Change the title, transitioning the new title in and the old one out in a given direction. + * @param {string} title The new title to show. + * @param {string} direction The direction to transition the new title in. + * Available: 'forward', 'back'. + */ + 'changeTitle', + /** + * @ngdoc method + * @name $ionicNavBarDelegate#getTitle + * @returns {string} The current title of the navbar. + */ + 'getTitle', + /** + * @ngdoc method + * @name $ionicNavBarDelegate#getPreviousTitle + * @returns {string} The previous title of the navbar. + */ + 'getPreviousTitle' + /** + * @ngdoc method + * @name $ionicNavBarDelegate#$getByHandle + * @param {string} handle + * @returns `delegateInstance` A delegate instance that controls only the + * navBars with delegate-handle matching the given handle. + * + * Example: `$ionicNavBarDelegate.$getByHandle('myHandle').setTitle('newTitle')` + */ +])); diff --git a/js/ext/angular/src/service/ionicPlatform.js b/js/angular/service/platform.js similarity index 88% rename from js/ext/angular/src/service/ionicPlatform.js rename to js/angular/service/platform.js index 1506dd6b8f..1ef66589ba 100644 --- a/js/ext/angular/src/service/ionicPlatform.js +++ b/js/angular/service/platform.js @@ -1,7 +1,3 @@ -(function(ionic) {'use strict'; - -angular.module('ionic.service.platform', []) - /** * @ngdoc service * @name $ionicPlatform @@ -12,11 +8,12 @@ angular.module('ionic.service.platform', []) * Used to detect the current platform, as well as do things like override the * Android back button in PhoneGap/Cordova. */ +IonicModule .provider('$ionicPlatform', function() { return { $get: ['$q', '$rootScope', function($q, $rootScope) { - return { + var self = { /** * @ngdoc method * @name $ionicPlatform#onHardwareBackButton @@ -65,12 +62,12 @@ angular.module('ionic.service.platform', []) * @returns {function} A function that, when called, will deregister * this backButtonAction. */ + $backButtonActions: {}, registerBackButtonAction: function(fn, priority, actionId) { - var self = this; if(!self._hasBackButtonHandler) { // add a back button listener if one hasn't been setup yet - $rootScope.$backButtonActions = {}; + self.$backButtonActions = {}; self.onHardwareBackButton(self.hardwareBackButtonClick); self._hasBackButtonHandler = true; } @@ -80,11 +77,11 @@ angular.module('ionic.service.platform', []) priority: (priority ? priority : 0), fn: fn }; - $rootScope.$backButtonActions[action.id] = action; + self.$backButtonActions[action.id] = action; // return a function to de-register this back button action return function() { - delete $rootScope.$backButtonActions[action.id]; + delete self.$backButtonActions[action.id]; }; }, @@ -95,9 +92,9 @@ angular.module('ionic.service.platform', []) // loop through all the registered back button actions // and only run the last one of the highest priority var priorityAction, actionId; - for(actionId in $rootScope.$backButtonActions) { - if(!priorityAction || $rootScope.$backButtonActions[actionId].priority >= priorityAction.priority) { - priorityAction = $rootScope.$backButtonActions[actionId]; + for(actionId in self.$backButtonActions) { + if(!priorityAction || self.$backButtonActions[actionId].priority >= priorityAction.priority) { + priorityAction = self.$backButtonActions[actionId]; } } if(priorityAction) { @@ -130,9 +127,8 @@ angular.module('ionic.service.platform', []) return q.promise; } }; + return self; }] }; }); - -})(ionic); diff --git a/js/ext/angular/src/service/ionicPopup.js b/js/angular/service/popup.js similarity index 98% rename from js/ext/angular/src/service/ionicPopup.js rename to js/angular/service/popup.js index beb212e84f..7f6ffe2a3a 100644 --- a/js/ext/angular/src/service/ionicPopup.js +++ b/js/angular/service/popup.js @@ -1,5 +1,5 @@ -var TPL_POPUP = +var POPUP_TPL = ''; -var CONTENT_POPUP_DEPRECATED = '$ionicPopup options.content has been deprecated. Use options.template instead.'; - -angular.module('ionic.service.popup', ['ionic.service.templateLoad']) +var POPUP_CONTENT_DEPRECATED = '$ionicPopup options.content has been deprecated. Use options.template instead.'; /** * @ngdoc service @@ -99,9 +97,8 @@ angular.module('ionic.service.popup', ['ionic.service.templateLoad']) * }; *}); *``` - - */ +IonicModule .factory('$ionicPopup', [ '$animate', '$ionicTemplateLoader', @@ -274,10 +271,10 @@ function($animate, $ionicTemplateLoader, $ionicBackdrop, $log, $q, $timeout, $ro buttons: [], }, options || {}); - deprecated.field(CONTENT_POPUP_DEPRECATED, $log.warn, options, 'content', options.content); + deprecated.field(POPUP_CONTENT_DEPRECATED, $log.warn, options, 'content', options.content); var popupPromise = $ionicTemplateLoader.compile({ - template: TPL_POPUP, + template: POPUP_TPL, scope: options.scope && options.scope.$new(), appendTo: $document[0].body }); diff --git a/js/ext/angular/src/controller/ionicScrollController.js b/js/angular/service/scrollDelegate.js similarity index 53% rename from js/ext/angular/src/controller/ionicScrollController.js rename to js/angular/service/scrollDelegate.js index c047f4abfb..7675f6d6fd 100644 --- a/js/ext/angular/src/controller/ionicScrollController.js +++ b/js/angular/service/scrollDelegate.js @@ -1,4 +1,3 @@ -angular.module('ionic.ui.scroll') /** * @ngdoc service @@ -58,7 +57,7 @@ angular.module('ionic.ui.scroll') * } * ``` */ - +IonicModule .service('$ionicScrollDelegate', delegateService([ /** * @ngdoc method @@ -190,189 +189,5 @@ angular.module('ionic.ui.scroll') * * Example: `$ionicScrollDelegate.$getByHandle('my-handle').scrollTop();` */ -])) - -/** - * @private - */ -.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(); - }); - }; -}]); +])); diff --git a/js/angular/service/sideMenuDelegate.js b/js/angular/service/sideMenuDelegate.js new file mode 100644 index 0000000000..728833592e --- /dev/null +++ b/js/angular/service/sideMenuDelegate.js @@ -0,0 +1,104 @@ +/** + * @ngdoc service + * @name $ionicSideMenuDelegate + * @module ionic + * + * @description + * Delegate for controlling the {@link ionic.directive:ionSideMenus} directive. + * + * Methods called directly on the $ionicSideMenuDelegate service will control all side + * menus. Use the {@link ionic.service:$ionicSideMenuDelegate#$getByHandle $getByHandle} + * method to control specific ionSideMenus instances. + * + * @usage + * + * ```html + * + * + * + * Content! + * + * + * + * Left Menu! + * + * + * + * ``` + * ```js + * function MainCtrl($scope, $ionicSideMenuDelegate) { + * $scope.toggleLeftSideMenu = function() { + * $ionicSideMenuDelegate.toggleLeft(); + * }; + * } + * ``` + */ +IonicModule +.service('$ionicSideMenuDelegate', delegateService([ + /** + * @ngdoc method + * @name $ionicSideMenuDelegate#toggleLeft + * @description Toggle the left side menu (if it exists). + * @param {boolean=} isOpen Whether to open or close the menu. + * Default: Toggles the menu. + */ + 'toggleLeft', + /** + * @ngdoc method + * @name $ionicSideMenuDelegate#toggleRight + * @description Toggle the right side menu (if it exists). + * @param {boolean=} isOpen Whether to open or close the menu. + * Default: Toggles the menu. + */ + 'toggleRight', + /** + * @ngdoc method + * @name $ionicSideMenuDelegate#getOpenRatio + * @description Gets the ratio of open amount over menu width. For example, a + * menu of width 100 that is opened by 50 pixels is 50% opened, and would return + * a ratio of 0.5. + * + * @returns {float} 0 if nothing is open, between 0 and 1 if left menu is + * opened/opening, and between 0 and -1 if right menu is opened/opening. + */ + 'getOpenRatio', + /** + * @ngdoc method + * @name $ionicSideMenuDelegate#isOpen + * @returns {boolean} Whether either the left or right menu is currently opened. + */ + 'isOpen', + /** + * @ngdoc method + * @name $ionicSideMenuDelegate#isOpenLeft + * @returns {boolean} Whether the left menu is currently opened. + */ + 'isOpenLeft', + /** + * @ngdoc method + * @name $ionicSideMenuDelegate#isOpenRight + * @returns {boolean} Whether the right menu is currently opened. + */ + 'isOpenRight', + /** + * @ngdoc method + * @name $ionicSideMenuDelegate#canDragContent + * @param {boolean=} canDrag Set whether the content can or cannot be dragged to open + * side menus. + * @returns {boolean} Whether the content can be dragged to open side menus. + */ + 'canDragContent' + /** + * @ngdoc method + * @name $ionicSideMenuDelegate#$getByHandle + * @param {string} handle + * @returns `delegateInstance` A delegate instance that controls only the + * {@link ionic.directive:ionSideMenus} directives with `delegate-handle` matching + * the given handle. + * + * Example: `$ionicSideMenuDelegate.$getByHandle('my-handle').toggleLeft();` + */ +])); + diff --git a/js/angular/service/slideBoxDelegate.js b/js/angular/service/slideBoxDelegate.js new file mode 100644 index 0000000000..7d0b29d664 --- /dev/null +++ b/js/angular/service/slideBoxDelegate.js @@ -0,0 +1,97 @@ +/** + * @ngdoc service + * @name $ionicSlideBoxDelegate + * @module ionic + * @description + * Delegate that controls the {@link ionic.directive:ionSlideBox} directive. + * + * Methods called directly on the $ionicSlideBoxDelegate service will control all side + * menus. Use the {@link ionic.service:$ionicSlideBoxDelegate#$getByHandle $getByHandle} + * method to control specific slide box instances. + * + * @usage + * + * ```html + * + * + * + *
+ * + *
+ *
+ * + *
+ * Slide 2! + *
+ *
+ *
+ * + * ``` + * ```js + * function MyCtrl($scope, $ionicSlideBoxDelegate) { + * $scope.nextSlide = function() { + * $ionicSlideBoxDelegate.next(); + * } + * } + * ``` + */ +IonicModule +.service('$ionicSlideBoxDelegate', delegateService([ + /** + * @ngdoc method + * @name $ionicSlideBoxDelegate#update + * @description + * Update the slidebox (for example if using Angular with ng-repeat, + * resize it for the elements inside). + */ + 'update', + /** + * @ngdoc method + * @name $ionicSlideBoxDelegate#slide + * @param {number} to The index to slide to. + * @param {number=} speed The number of milliseconds for the change to take. + */ + 'slide', + /** + * @ngdoc method + * @name $ionicSlideBoxDelegate#previous + * @description Go to the previous slide. Wraps around if at the beginning. + */ + 'previous', + /** + * @ngdoc method + * @name $ionicSlideBoxDelegate#next + * @description Go to the next slide. Wraps around if at the end. + */ + 'next', + /** + * @ngdoc method + * @name $ionicSlideBoxDelegate#stop + * @description Stop sliding. The slideBox will not move again until + * explicitly told to do so. + */ + 'stop', + /** + * @ngdoc method + * @name $ionicSlideBoxDelegate#currentIndex + * @returns number The index of the current slide. + */ + 'currentIndex', + /** + * @ngdoc method + * @name $ionicSlideBoxDelegate#slidesCount + * @returns number The number of slides there are currently. + */ + 'slidesCount' + /** + * @ngdoc method + * @name $ionicSlideBoxDelegate#$getByHandle + * @param {string} handle + * @returns `delegateInstance` A delegate instance that controls only the + * {@link ionic.directive:ionSlideBox} directives with `delegate-handle` matching + * the given handle. + * + * Example: `$ionicSlideBoxDelegate.$getByHandle('my-handle').stop();` + */ +])); + diff --git a/js/angular/service/tabsDelegate.js b/js/angular/service/tabsDelegate.js new file mode 100644 index 0000000000..0d740539e8 --- /dev/null +++ b/js/angular/service/tabsDelegate.js @@ -0,0 +1,68 @@ +/** + * @ngdoc service + * @name $ionicTabsDelegate + * @module ionic + * + * @description + * Delegate for controlling the {@link ionic.directive:ionTabs} directive. + * + * Methods called directly on the $ionicTabsDelegate service will control all ionTabs + * directives. Use the {@link ionic.service:$ionicTabsDelegate#$getByHandle $getByHandle} + * method to control specific ionTabs instances. + * + * @usage + * + * ```html + * + * + * + * + * Hello tab 1! + * + * + * Hello tab 2! + * + * + * + * ``` + * ```js + * function MyCtrl($scope, $ionicTabsDelegate) { + * $scope.selectTabWithIndex = function(index) { + * $ionicTabsDelegate.select(index); + * } + * } + * ``` + */ +IonicModule +.service('$ionicTabsDelegate', delegateService([ + /** + * @ngdoc method + * @name $ionicTabsDelegate#select + * @description Select the tab matching the given index. + * + * @param {number} index Index of the tab to select. + * @param {boolean=} shouldChangeHistory Whether this selection should load this tab's + * view history (if it exists) and use it, or just load the default page. + * Default false. + * Hint: you probably want this to be true if you have an + * {@link ionic.directive:ionNavView} inside your tab. + */ + 'select', + /** + * @ngdoc method + * @name $ionicTabsDelegate#selectedIndex + * @returns `number` The index of the selected tab, or -1. + */ + 'selectedIndex' + /** + * @ngdoc method + * @name $ionicTabsDelegate#$getByHandle + * @param {string} handle + * @returns `delegateInstance` A delegate instance that controls only the + * {@link ionic.directive:ionTabs} directives with `delegate-handle` matching + * the given handle. + * + * Example: `$ionicTabsDelegate.$getByHandle('my-handle').select(0);` + */ +])) + diff --git a/js/ext/angular/src/service/ionicTemplateLoader.js b/js/angular/service/templateLoader.js similarity index 95% rename from js/ext/angular/src/service/ionicTemplateLoader.js rename to js/angular/service/templateLoader.js index b97e47b0e6..d0b957f764 100644 --- a/js/ext/angular/src/service/ionicTemplateLoader.js +++ b/js/angular/service/templateLoader.js @@ -1,8 +1,4 @@ -angular.module('ionic.service.templateLoad', []) - -/** - * @private - */ +IonicModule .factory('$ionicTemplateLoader', [ '$compile', '$controller', diff --git a/js/ext/angular/src/service/ionicView.js b/js/angular/service/viewService.js similarity index 95% rename from js/ext/angular/src/service/ionicView.js rename to js/angular/service/viewService.js index 0e79afe1be..304ac1c044 100644 --- a/js/ext/angular/src/service/ionicView.js +++ b/js/angular/service/viewService.js @@ -1,12 +1,17 @@ -angular.module('ionic.service.view', ['ui.router', 'ionic.service.platform']) - - /** * @private * TODO document */ -.run(['$rootScope', '$state', '$location', '$document', '$animate', '$ionicPlatform', - function( $rootScope, $state, $location, $document, $animate, $ionicPlatform) { +IonicModule +.run([ + '$rootScope', + '$state', + '$location', + '$document', + '$animate', + '$ionicPlatform', + '$ionicViewService', +function($rootScope, $state, $location, $document, $animate, $ionicPlatform, $ionicViewService) { // init the variables that keep track of the view history $rootScope.$viewHistory = { @@ -18,6 +23,13 @@ angular.module('ionic.service.view', ['ui.router', 'ionic.service.platform']) disabledRegistrableTagNames: [] }; + // set that these directives should not animate when transitioning + // to it. Instead, the children directives would animate + if ($ionicViewService.disableRegisterByTagName) { + $ionicViewService.disableRegisterByTagName('ion-tabs'); + $ionicViewService.disableRegisterByTagName('ion-side-menus'); + } + $rootScope.$on('viewState.changeHistory', function(e, data) { if(!data) return; @@ -71,9 +83,14 @@ angular.module('ionic.service.view', ['ui.router', 'ionic.service.platform']) }]) -.factory('$ionicViewService', ['$rootScope', '$state', '$location', '$window', '$injector', - function( $rootScope, $state, $location, $window, $injector) { - var $animate = $injector.has('$animate') ? $injector.get('$animate') : false; +.factory('$ionicViewService', [ + '$rootScope', + '$state', + '$location', + '$window', + '$injector', + '$animate', +function($rootScope, $state, $location, $window, $injector, $animate) { var View = function(){}; View.prototype.initialize = function(data) { @@ -412,11 +429,7 @@ angular.module('ionic.service.view', ['ui.router', 'ionic.service.platform']) var doAnimation; // climb up the DOM and see which animation classname to use, if any - var animationClass = angular.isDefined(navViewScope.$nextAnimation) ? - navViewScope.$nextAnimation : - getParentAnimationClass(navViewElement[0]); - - navViewScope.$nextAnimation = undefined; + var animationClass = getParentAnimationClass(navViewElement[0]); function getParentAnimationClass(el) { var className = ''; diff --git a/js/controllers/navController.js b/js/controllers/navController.js deleted file mode 100644 index 29460f5670..0000000000 --- a/js/controllers/navController.js +++ /dev/null @@ -1,152 +0,0 @@ -(function(ionic) { -'use strict'; - -/** - * The NavController makes it easy to have a stack - * of views or screens that can be pushed and popped - * for a dynamic navigation flow. This API is modelled - * off of the UINavigationController in iOS. - * - * The NavController can drive a nav bar to show a back button - * if the stack can be poppped to go back to the last view, and - * it will handle updating the title of the nav bar and processing animations. - */ -ionic.controllers.NavController = ionic.controllers.ViewController.inherit({ - initialize: function(opts) { - var _this = this; - - this.navBar = opts.navBar; - this.content = opts.content; - this.controllers = opts.controllers || []; - - this._updateNavBar(); - - // TODO: Is this the best way? - this.navBar.shouldGoBack = function() { - _this.pop(); - }; - }, - - /** - * @return {array} the array of controllers on the stack. - */ - getControllers: function() { - return this.controllers; - }, - - /** - * @return {object} the controller at the top of the stack. - */ - getTopController: function() { - return this.controllers[this.controllers.length-1]; - }, - - /** - * Push a new controller onto the navigation stack. The new controller - * will automatically become the new visible view. - * - * @param {object} controller the controller to push on the stack. - */ - push: function(controller) { - var last = this.controllers[this.controllers.length - 1]; - - this.controllers.push(controller); - - // Indicate we are switching controllers - var shouldSwitch = this.switchingController && this.switchingController(controller) || true; - - // Return if navigation cancelled - if(shouldSwitch === false) - return; - - // Actually switch the active controllers - if(last) { - last.isVisible = false; - last.visibilityChanged && last.visibilityChanged('push'); - } - - // Grab the top controller on the stack - var next = this.controllers[this.controllers.length - 1]; - - next.isVisible = true; - // Trigger visibility change, but send 'first' if this is the first page - next.visibilityChanged && next.visibilityChanged(last ? 'push' : 'first'); - - this._updateNavBar(); - - return controller; - }, - - /** - * Pop the top controller off the stack, and show the last one. This is the - * "back" operation. - * - * @return {object} the last popped controller - */ - pop: function() { - var next, last; - - // Make sure we keep one on the stack at all times - if(this.controllers.length < 2) { - return; - } - - // Grab the controller behind the top one on the stack - last = this.controllers.pop(); - if(last) { - last.isVisible = false; - last.visibilityChanged && last.visibilityChanged('pop'); - } - - // Remove the old one - //last && last.detach(); - - next = this.controllers[this.controllers.length - 1]; - - // TODO: No DOM stuff here - //this.content.el.appendChild(next.el); - next.isVisible = true; - next.visibilityChanged && next.visibilityChanged('pop'); - - // Switch to it (TODO: Animate or such things here) - - this._updateNavBar(); - - return last; - }, - - /** - * Show the NavBar (if any) - */ - showNavBar: function() { - if(this.navBar) { - this.navBar.show(); - } - }, - - /** - * Hide the NavBar (if any) - */ - hideNavBar: function() { - if(this.navBar) { - this.navBar.hide(); - } - }, - - // Update the nav bar after a push or pop - _updateNavBar: function() { - if(!this.getTopController() || !this.navBar) { - return; - } - - this.navBar.setTitle(this.getTopController().title); - - if(this.controllers.length > 1) { - this.navBar.showBackButton(true); - } else { - this.navBar.showBackButton(false); - } - } -}); - -})(window.ionic); diff --git a/js/controllers/tabBarController.js b/js/controllers/tabBarController.js deleted file mode 100644 index 5144b196d9..0000000000 --- a/js/controllers/tabBarController.js +++ /dev/null @@ -1,143 +0,0 @@ -(function(ionic) { -'use strict'; - -/** - * The TabBarController handles a set of view controllers powered by a tab strip - * at the bottom (or possibly top) of a screen. - * - * The API here is somewhat modelled off of UITabController in the sense that the - * controllers actually define what the tab will look like (title, icon, etc.). - * - * Tabs shouldn't be interacted with through your own code. Instead, use the controller - * methods which will power the tab bar. - */ -ionic.controllers.TabBarController = ionic.controllers.ViewController.inherit({ - initialize: function(options) { - this.tabBar = options.tabBar; - - this._bindEvents(); - - this.controllers = []; - - var controllers = options.controllers || []; - - for(var i = 0; i < controllers.length; i++) { - this.addController(controllers[i]); - } - - // Bind or set our tabWillChange callback - this.controllerWillChange = options.controllerWillChange || function(controller) {}; - this.controllerChanged = options.controllerChanged || function(controller) {}; - - // Try to select the first controller if we have one - this.setSelectedController(0); - }, - // Start listening for events on our tab bar - _bindEvents: function() { - var _this = this; - - this.tabBar.tryTabSelect = function(index) { - _this.setSelectedController(index); - }; - }, - - - selectController: function(index) { - var shouldChange = true; - - // Check if we should switch to this tab. This lets the app - // cancel tab switches if the context isn't right, for example. - if(this.controllerWillChange) { - if(this.controllerWillChange(this.controllers[index], index) === false) { - shouldChange = false; - } - } - - if(shouldChange) { - this.setSelectedController(index); - } - }, - - // Force the selection of a controller at the given index - setSelectedController: function(index) { - if(index >= this.controllers.length) { - return; - } - var lastController = this.selectedController; - var lastIndex = this.selectedIndex; - - this.selectedController = this.controllers[index]; - this.selectedIndex = index; - - this._showController(index); - this.tabBar.setSelectedItem(index); - - this.controllerChanged && this.controllerChanged(lastController, lastIndex, this.selectedController, this.selectedIndex); - }, - - _showController: function(index) { - var c; - - for(var i = 0, j = this.controllers.length; i < j; i ++) { - c = this.controllers[i]; - //c.detach && c.detach(); - c.isVisible = false; - c.visibilityChanged && c.visibilityChanged(); - } - - c = this.controllers[index]; - //c.attach && c.attach(); - c.isVisible = true; - c.visibilityChanged && c.visibilityChanged(); - }, - - _clearSelected: function() { - this.selectedController = null; - this.selectedIndex = -1; - }, - - // Return the tab at the given index - getController: function(index) { - return this.controllers[index]; - }, - - // Return the current tab list - getControllers: function() { - return this.controllers; - }, - - // Get the currently selected controller - getSelectedController: function() { - return this.selectedController; - }, - - // Get the index of the currently selected controller - getSelectedControllerIndex: function() { - return this.selectedIndex; - }, - - // Add a tab - addController: function(controller) { - this.controllers.push(controller); - - this.tabBar.addItem({ - title: controller.title, - icon: controller.icon, - badge: controller.badge - }); - - // If we don't have a selected controller yet, select the first one. - if(!this.selectedController) { - this.setSelectedController(0); - } - }, - - // Set the tabs and select the first - setControllers: function(controllers) { - this.controllers = controllers; - this._clearSelected(); - this.selectController(0); - }, -}); - -})(window.ionic); diff --git a/js/ext/angular/src/directive/ionicContent.js b/js/ext/angular/src/directive/ionicContent.js deleted file mode 100644 index 8c7f65b9c4..0000000000 --- a/js/ext/angular/src/directive/ionicContent.js +++ /dev/null @@ -1,383 +0,0 @@ -(function() { -'use strict'; - -angular.module('ionic.ui.content', ['ionic.ui.scroll']) - -/** - * Panel is a simple 100% width and height, fixed panel. It's meant for content to be - * added to it, or animated around. - */ -/** - * @ngdoc directive - * @name ionPane - * @module ionic - * @restrict E - * - * @description A simple container that fits content, with no side effects. Adds the 'pane' class to the element. - */ -.directive('ionPane', function() { - return { - restrict: 'E', - link: function(scope, element, attr) { - element.addClass('pane'); - } - }; -}) - -/** - * @ngdoc directive - * @name ionContent - * @module ionic - * @delegate ionic.service:$ionicScrollDelegate - * @restrict E - * - * @description - * The ionContent directive provides an easy to use content area that can be configured - * to use Ionic's custom Scroll View, or the built in overflow scrolling of the browser. - * - * While we recommend using the custom Scroll features in Ionic in most cases, sometimes - * (for performance reasons) only the browser's native overflow scrolling will suffice, - * and so we've made it easy to toggle between the Ionic scroll implementation and - * overflow scrolling. - * - * You can implement pull-to-refresh with the {@link ionic.directive:ionRefresher} - * directive, and infinite scrolling with the {@link ionic.directive:ionInfiniteScroll} - * directive. - * - * @param {string=} delegate-handle The handle used to identify this scrollView - * with {@link ionic.service:$ionicScrollDelegate}. - * @param {boolean=} padding Whether to add padding to the content. - * of the content. Defaults to true on iOS, false on Android. - * @param {boolean=} scroll Whether to allow scrolling of content. Defaults to true. - * @param {boolean=} overflow-scroll Whether to use overflow-scrolling instead of - * Ionic scroll. - * @param {boolean=} has-bouncing Whether to allow scrolling to bounce past the edges - * 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. - */ -.directive('ionContent', [ - '$timeout', - '$controller', - '$ionicBind', -function($timeout, $controller, $ionicBind) { - return { - restrict: 'E', - require: '^?ionNavView', - scope: true, - compile: function(element, attr) { - var innerElement; - - element.addClass('scroll-content'); - - if (attr.scroll != 'false') { - //We cannot use normal transclude here because it breaks element.data() - //inheritance on compile - innerElement = angular.element('
'); - innerElement.append(element.contents()); - element.append(innerElement); - } - - return { pre: prelink }; - function prelink($scope, $element, $attr, navViewCtrl) { - var parentScope = $scope.$parent; - $scope.$watch(function() { - return (parentScope.$hasHeader ? ' has-header' : '') + - (parentScope.$hasSubheader ? ' has-subheader' : '') + - (parentScope.$hasFooter ? ' has-footer' : '') + - (parentScope.$hasSubfooter ? ' has-subfooter' : '') + - (parentScope.$hasTabs ? ' has-tabs' : '') + - (parentScope.$hasTabsTop ? ' has-tabs-top' : ''); - }, function(className, oldClassName) { - $element.removeClass(oldClassName); - $element.addClass(className); - }); - - //Only this ionContent should use these variables from parent scopes - $scope.$hasHeader = $scope.$hasSubheader = - $scope.$hasFooter = $scope.$hasSubfooter = - $scope.$hasTabs = $scope.$hasTabsTop = - false; - - $ionicBind($scope, $attr, { - $onScroll: '&onScroll', - $onScrollComplete: '&onScrollComplete', - hasBouncing: '@', - scroll: '@', - padding: '@', - hasScrollX: '@', - hasScrollY: '@', - scrollbarX: '@', - scrollbarY: '@', - startX: '@', - startY: '@', - scrollEventInterval: '@' - }); - - if (angular.isDefined($attr.padding)) { - $scope.$watch($attr.padding, function(newVal) { - (innerElement || $element).toggleClass('padding', !!newVal); - }); - } - - if ($scope.scroll === "false") { - //do nothing - } else if(attr.overflowScroll === "true") { - $element.addClass('overflow-scroll'); - } else { - $controller('$ionicScroll', { - $scope: $scope, - scrollViewOptions: { - el: $element[0], - delegateHandle: attr.delegateHandle, - bouncing: $scope.$eval($scope.hasBouncing), - startX: $scope.$eval($scope.startX) || 0, - startY: $scope.$eval($scope.startY) || 0, - scrollbarX: $scope.$eval($scope.scrollbarX) !== false, - scrollbarY: $scope.$eval($scope.scrollbarY) !== false, - scrollingX: $scope.$eval($scope.hasScrollX) === true, - scrollingY: $scope.$eval($scope.hasScrollY) !== false, - scrollEventInterval: parseInt($scope.scrollEventInterval, 10) || 20, - scrollingComplete: function() { - $scope.$onScrollComplete({ - scrollTop: this.__scrollTop, - scrollLeft: this.__scrollLeft - }); - } - } - }); - } - - } - } - }; -}]) - -/** - * @ngdoc directive - * @name ionRefresher - * @module ionic - * @restrict E - * @parent ionic.directive:ionContent, ionic.directive:ionScroll - * @description - * Allows you to add pull-to-refresh to a scrollView. - * - * Place it as the first child of your {@link ionic.directive:ionContent} or - * {@link ionic.directive:ionScroll} element. - * - * When refreshing is complete, $broadcast the 'scroll.refreshComplete' event - * from your controller. - * - * @usage - * - * ```html - * - * - * - * - * - * - * - * ``` - * ```js - * angular.module('testApp', ['ionic']) - * .controller('MyController', function($scope, $http) { - * $scope.items = [1,2,3]; - * $scope.doRefresh = function() { - * $http.get('/new-items') - * .success(function(newItems) { - * $scope.items = newItems; - * }) - * .finally(function() { - * // Stop the ion-refresher from spinning - * $scope.$broadcast('scroll.refreshComplete'); - * }); - * }; - * }); - * ``` - * - * @param {expression=} on-refresh Called when the user pulls down enough and lets go - * of the refresher. - * @param {expression=} on-pulling Called when the user starts to pull down - * on the refresher. - * @param {string=} pulling-icon The icon to display while the user is pulling down. - * Default: 'ion-arrow-down-c'. - * @param {string=} pulling-text The text to display while the user is pulling down. - * @param {string=} refreshing-icon The icon to display after user lets go of the - * refresher. - * @param {string=} refreshing-text The text to display after the user lets go of - * the refresher. - * - */ -.directive('ionRefresher', ['$ionicBind', function($ionicBind) { - return { - restrict: 'E', - replace: true, - require: '^$ionicScroll', - template: - '
' + - '
' + - '' + - '
' + - '' + - '
' + - '
' + - '
', - compile: function($element, $attrs) { - if (angular.isUndefined($attrs.pullingIcon)) { - $attrs.$set('pullingIcon', 'ion-arrow-down-c'); - } - if (angular.isUndefined($attrs.refreshingIcon)) { - $attrs.$set('refreshingIcon', 'ion-loading-d'); - } - return function($scope, $element, $attrs, scrollCtrl) { - $ionicBind($scope, $attrs, { - pullingIcon: '@', - pullingText: '@', - refreshingIcon: '@', - refreshingText: '@', - $onRefresh: '&onRefresh', - $onPulling: '&onPulling' - }); - - scrollCtrl._setRefresher($scope, $element[0]); - $scope.$on('scroll.refreshComplete', function() { - $element[0].classList.remove('active'); - scrollCtrl.scrollView.finishPullToRefresh(); - }); - }; - } - }; -}]) - -/** - * @ngdoc directive - * @name ionInfiniteScroll - * @module ionic - * @parent ionic.directive:ionContent, ionic.directive:ionScroll - * @restrict E - * - * @description - * The ionInfiniteScroll directive allows you to call a function whenever - * the user gets to the bottom of the page or near the bottom of the page. - * - * The expression you pass in for `on-infinite` is called when the user scrolls - * greater than `distance` away from the bottom of the content. - * - * @param {expression} on-infinite What to call when the scroller reaches the - * bottom. - * @param {string=} distance The distance from the bottom that the scroll must - * reach to trigger the on-infinite expression. Default: 1%. - * @param {string=} icon The icon to show while loading. Default: 'ion-loading-d'. - * - * @usage - * ```html - * - * - * - * - * ``` - * ```js - * function MyController($scope, $http) { - * $scope.items = []; - * $scope.loadMore = function() { - * $http.get('/more-items').success(function(items) { - * useItems(items); - * $scope.$broadcast('scroll.infiniteScrollComplete'); - * }); - * }; - * } - * ``` - * - * An easy to way to stop infinite scroll once there is no more data to load - * is to use angular's `ng-if` directive: - * - * ```html - * - * - * ``` - */ -.directive('ionInfiniteScroll', ['$timeout', function($timeout) { - function calculateMaxValue(distance, maximum, isPercent) { - return isPercent ? - maximum * (1 - parseInt(distance,10) / 100) : - maximum - parseInt(distance, 10); - } - return { - restrict: 'E', - require: ['^$ionicScroll', 'ionInfiniteScroll'], - template: - '
' + - '
' + - '' + - '
' + - '
', - scope: true, - controller: ['$scope', '$attrs', function($scope, $attrs) { - this.isLoading = false; - this.scrollView = null; //given by link function - this.getMaxScroll = function() { - var distance = ($attrs.distance || '1%').trim(); - var isPercent = distance.indexOf('%') !== -1; - var maxValues = this.scrollView.getScrollMax(); - return { - left: this.scrollView.options.scrollingX ? - calculateMaxValue(distance, maxValues.left, isPercent) : - -1, - top: this.scrollView.options.scrollingY ? - calculateMaxValue(distance, maxValues.top, isPercent) : - -1 - }; - }; - }], - link: function($scope, $element, $attrs, ctrls) { - var scrollCtrl = ctrls[0]; - var infiniteScrollCtrl = ctrls[1]; - var scrollView = infiniteScrollCtrl.scrollView = scrollCtrl.scrollView; - - $scope.icon = function() { - return angular.isDefined($attrs.icon) ? $attrs.icon : 'ion-loading-d'; - }; - - $scope.$on('scroll.infiniteScrollComplete', function() { - $element[0].classList.remove('active'); - $timeout(function() { - scrollView.resize(); - }, 0, false); - infiniteScrollCtrl.isLoading = false; - }); - $scope.$on('$destroy', function() { - scrollCtrl.$element.off('scroll', checkBounds); - }); - - var checkBounds = ionic.animationFrameThrottle(checkInfiniteBounds); - - //Check bounds on start, after scrollView is fully rendered - setTimeout(checkBounds); - scrollCtrl.$element.on('scroll', checkBounds); - - function checkInfiniteBounds() { - if (infiniteScrollCtrl.isLoading) return; - - var scrollValues = scrollView.getValues(); - var maxScroll = infiniteScrollCtrl.getMaxScroll(); - - if ((maxScroll.left !== -1 && scrollValues.left >= maxScroll.left) || - (maxScroll.top !== -1 && scrollValues.top >= maxScroll.top)) { - $element[0].classList.add('active'); - infiniteScrollCtrl.isLoading = true; - $scope.$parent && $scope.$parent.$apply($attrs.onInfinite || ''); - } - } - } - }; -}]); - -})(); diff --git a/js/ext/angular/src/directive/ionicList.js b/js/ext/angular/src/directive/ionicList.js deleted file mode 100644 index 867f8fca16..0000000000 --- a/js/ext/angular/src/directive/ionicList.js +++ /dev/null @@ -1,520 +0,0 @@ -(function() { - 'use strict'; - - var TPL_CONTENT_ANCHOR = - ''; - var TPL_CONTENT = - '
'; - var TPL_DELETE_BUTTON = - '
' + - '
'; - var TPL_REORDER_BUTTON = - '
' + - '
'; - var TPL_OPTION_BUTTONS = - ''; - - angular.module('ionic.ui.list', ['ngAnimate']) - - /** - * @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 - * - * - * - * > - * {% raw %}Hello, {{i}}!{% endraw %} - * - * - * - * - * ``` - * ```js - * function MyCtrl($scope, $ionicListDelegate) { - * $scope.showDeleteButtons = function() { - * $ionicListDelegate.showDelete(true); - * }; - * } - * ``` - */ - .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(); - }; - }]) - -/** - * @ngdoc directive - * @name ionList - * @module ionic - * @delegate ionic.service:$ionicListDelegate - * @codepen JsHjf - * @restrict E - * @description - * The List is a widely used interface element in almost any mobile app, and can include - * content ranging from basic text all the way to buttons, toggles, icons, and thumbnails. - * - * Both the list, which contains items, and the list items themselves can be any HTML - * element. The containing element requires the `list` class and each list item requires - * the `item` class. - * - * However, using the ionList and ionItem directives make it easy to support various - * interaction modes such as swipe to edit, drag to reorder, and removing items. - * - * Related: {@link ionic.directive:ionItem}, {@link ionic.directive:ionOptionButton} - * {@link ionic.directive:ionReorderButton}, {@link ionic.directive:ionDeleteButton}, [`list CSS documentation`](/docs/components/#list). - * - * @usage - * - * Basic Usage: - * - * ```html - * - * - * {% raw %}Hello, {{item}}!{% endraw %} - * - * - * ``` - * - * Advanced Usage: Thumbnails, Delete buttons, Reordering, Swiping - * - * ```html - * - * - * - * {% raw %} - *

{{item.title}}

- *

{{item.description}}

{% endraw %} - * - * Share - * - * - * Edit - * - * - * - * - * - * - *
- *
- * ``` - * - * @param {string=} delegate-handle The handle used to identify this list with - * {@link ionic.service:$ionicListDelegate}. - * @param show-delete {boolean=} Whether the delete buttons for the items in the list are - * currently shown or hidden. - * @param show-reorder {boolean=} Whether the reorder buttons for the items in the list are - * currently shown or hidden. - * @param can-swipe {boolean=} Whether the items in the list are allowed to be swiped to reveal - * option buttons. Default: true. - */ -.directive('ionList', [ - '$animate', - '$timeout', -function($animate, $timeout) { - return { - restrict: 'E', - require: ['ionList', '^?$ionicScroll'], - controller: '$ionicList', - compile: function($element, $attr) { - var listEl = angular.element('
') - .append( $element.contents() ); - $element.append(listEl); - - return function($scope, $element, $attrs, ctrls) { - var listCtrl = ctrls[0]; - var scrollCtrl = ctrls[1]; - - //Wait for child elements to render... - $timeout(init); - - function init() { - var listView = listCtrl.listView = new ionic.views.ListView({ - el: $element[0], - listEl: $element.children()[0], - scrollEl: scrollCtrl && scrollCtrl.element, - scrollView: scrollCtrl && scrollCtrl.scrollView, - onReorder: function(el, oldIndex, newIndex) { - var itemScope = angular.element(el).scope(); - if (itemScope && itemScope.$onReorder) { - itemScope.$onReorder(oldIndex, newIndex); - } - }, - canSwipe: function() { - return listCtrl.canSwipeItems(); - } - }); - - if (angular.isDefined($attr.canSwipe)) { - $scope.$watch('!!(' + $attr.canSwipe + ')', function(value) { - listCtrl.canSwipeItems(value); - }); - } - - if (angular.isDefined($attr.showDelete)) { - $scope.$watch('!!(' + $attr.showDelete + ')', function(value) { - listCtrl.showDelete(value); - }); - } - if (angular.isDefined($attr.showReorder)) { - $scope.$watch('!!(' + $attr.showReorder + ')', function(value) { - listCtrl.showReorder(value); - }); - } - - $scope.$watch(function() { - return listCtrl.showDelete(); - }, function(isShown, wasShown) { - //Only use isShown=false if it was already shown - if (!isShown && !wasShown) { return; } - - if (isShown) listCtrl.closeOptionButtons(); - - $element.children().toggleClass('list-left-editing', isShown); - toggleNgHide('.item-delete.item-left-edit', isShown); - }); - $scope.$watch(function() { - return listCtrl.showReorder(); - }, function(isShown, wasShown) { - //Only use isShown=false if it was already shown - if (!isShown && !wasShown) { return; } - - if (isShown) listCtrl.closeOptionButtons(); - listCtrl.showReorder(isShown); - - $element.children().toggleClass('list-right-editing', isShown); - toggleNgHide('.item-reorder.item-right-edit', isShown); - }); - - function toggleNgHide(selector, shouldShow) { - angular.forEach($element[0].querySelectorAll(selector), function(node) { - if (shouldShow) $animate.removeClass(angular.element(node), 'ng-hide'); - else $animate.addClass(angular.element(node), 'ng-hide'); - }); - } - } - - }; - } - }; -}]) - -.controller('$ionicItem', [ - '$scope', - '$element', -function($scope, $element) { - this.$element = $element; - this.$scope = $scope; -}]) - -/** - * @ngdoc directive - * @name ionItem - * @parent ionic.directive:ionList - * @module ionic - * @restrict E - * Creates a list-item that can easily be swiped, - * deleted, reordered, edited, and more. - * - * See {@link ionic.directive:ionList} for a complete example & explanation. - * - * Can be assigned any item class name. See the - * [list CSS documentation](/docs/components/#list). - * - * @usage - * - * ```html - * - * Hello! - * - * ``` - */ -.directive('ionItem', ['$animate', '$compile', function($animate, $compile) { - return { - restrict: 'E', - controller: '$ionicItem', - priorty: Number.MAX_VALUE, - require: ['ionItem', '^ionList'], - scope: true, - compile: function($element, $attrs) { - var isAnchor = angular.isDefined($attrs.href) || angular.isDefined($attrs.ngHref); - var isComplexItem = isAnchor || - //Lame way of testing, but we have to know at compile what to do with the element - /ion-(delete|option|reorder)-button/.test($element.html()); - - if (isComplexItem) { - var innerElement = angular.element(isAnchor ? TPL_CONTENT_ANCHOR : TPL_CONTENT); - innerElement.append($element.contents()); - - $element.append(innerElement); - $element.addClass('item item-complex'); - } else { - $element.addClass('item'); - } - - return function link($scope, $element, $attrs) { - $scope.$href = function() { - return $attrs.href || $attrs.ngHref; - }; - }; - } - }; -}]) - -/** - * @ngdoc directive - * @name ionDeleteButton - * @parent ionic.directive:ionItem - * @module ionic - * @restrict E - * Creates a delete button inside a list item, that is visible when the - * {@link ionic.directive:ionList ionList parent's} `show-delete` evaluates to true or - * `$ionicListDelegate.showDelete(true)` is called. - * - * Takes any ionicon as a class. - * - * See {@link ionic.directive:ionList} for a complete example & explanation. - * - * @usage - * - * ```html - * - * - * - * Hello, list item! - * - * - * - * Show Delete? - * - * ``` - */ -.directive('ionDeleteButton', [function() { - return { - restrict: 'E', - require: '^ionItem', - //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, - compile: function($element, $attr) { - //Add the classes we need during the compile phase, so that they stay - //even if something else like ngIf removes the element and re-addss it - $attr.$set('class', ($attr.class || '') + ' button icon button-icon', true); - return function($scope, $element, $attr, itemCtrl) { - var container = angular.element(TPL_DELETE_BUTTON); - container.append($element); - itemCtrl.$element.append(container).addClass('item-left-editable'); - }; - } - }; -}]) - -/** - * @ngdoc directive - * @name ionReorderButton - * @parent ionic.directive:ionItem - * @module ionic - * @restrict E - * Creates a reorder button inside a list item, that is visible when the - * {@link ionic.directive:ionList ionList parent's} `show-reorder` evaluates to true or - * `$ionicListDelegate.showReorder(true)` is called. - * - * 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). - * - * See {@link ionic.directive:ionList} for a complete example. - * - * @usage - * - * ```html - * - * - * Item {{$index}} - * - * - * - * - * ``` - * ```js - * function MyCtrl($scope) { - * $scope.items = [1, 2, 3, 4]; - * $scope.moveItem = function(item, fromIndex, toIndex) { - * //Move the item in the array - * $scope.items.splice(fromIndex, 1); - * $scope.items.splice(toIndex, 0, item); - * }; - * } - * ``` - * - * @param {expression=} on-reorder Expression to call when an item is reordered. - * Parameters given: $fromIndex, $toIndex. - */ -.directive('ionReorderButton', [function() { - return { - restrict: 'E', - require: '^ionItem', - priority: Number.MAX_VALUE, - compile: function($element, $attr) { - $attr.$set('class', ($attr.class || '') + ' button icon button-icon', true); - $element[0].setAttribute('data-prevent-scroll', true); - return function($scope, $element, $attr, itemCtrl) { - $scope.$onReorder = function(oldIndex, newIndex) { - $scope.$eval($attr.onReorder, { - $fromIndex: oldIndex, - $toIndex: newIndex - }); - }; - - var container = angular.element(TPL_REORDER_BUTTON); - container.append($element); - itemCtrl.$element.append(container).addClass('item-right-editable'); - }; - } - }; -}]) - -/** - * @ngdoc directive - * @name ionOptionButton - * @parent ionic.directive:ionItem - * @module ionic - * @restrict E - * Creates an option button inside a list item, that is visible when the item is swiped - * to the left by the user. Swiped open option buttons can be hidden with - * {@link ionic.directive:$ionicListDelegate#closeOptionButtons $ionicListDelegate#closeOptionButtons}. - * - * Can be assigned any button class. - * - * See {@link ionic.directive:ionList} for a complete example & explanation. - * - * @usage - * - * ```html - * - * - * I love kittens! - * Share - * Edit - * - * - * ``` - */ -.directive('ionOptionButton', ['$compile', function($compile) { - return { - restrict: 'E', - require: '^ionItem', - priority: Number.MAX_VALUE, - compile: function($element, $attr) { - $attr.$set('class', ($attr.class || '') + ' button', true); - return function($scope, $element, $attr, itemCtrl) { - if (!itemCtrl.optionsContainer) { - itemCtrl.optionsContainer = angular.element(TPL_OPTION_BUTTONS); - itemCtrl.$element.append(itemCtrl.optionsContainer); - } - itemCtrl.optionsContainer.append($element); - }; - } - }; -}]); - -})(); diff --git a/js/ext/angular/src/directive/ionicNavBar.js b/js/ext/angular/src/directive/ionicNavBar.js deleted file mode 100644 index ce6119ba62..0000000000 --- a/js/ext/angular/src/directive/ionicNavBar.js +++ /dev/null @@ -1,491 +0,0 @@ - -angular.module('ionic.ui.navBar', ['ionic.service.view', 'ngSanitize']) - -/** - * @ngdoc service - * @name $ionicNavBarDelegate - * @module ionic - * @description - * Delegate for controlling the {@link ionic.directive:ionNavBar} directive. - * - * @usage - * - * ```html - * - * - * - * - * - * ``` - * ```js - * function MyCtrl($scope, $ionicNavBarDelegate) { - * $scope.setNavTitle = function(title) { - * $ionicNavBarDelegate.setTitle(title); - * } - * } - * ``` - */ -.service('$ionicNavBarDelegate', delegateService([ - /** - * @ngdoc method - * @name $ionicNavBarDelegate#back - * @description Goes back in the view history. - * @param {DOMEvent=} event The event object (eg from a tap event) - */ - 'back', - /** - * @ngdoc method - * @name $ionicNavBarDelegate#align - * @description Aligns the title with the buttons in a given direction. - * @param {string=} direction The direction to the align the title text towards. - * Available: 'left', 'right', 'center'. Default: 'center'. - */ - 'align', - /** - * @ngdoc method - * @name $ionicNavBarDelegate#showBackButton - * @description - * Set/get whether the {@link ionic.directive:ionNavBackButton} is shown - * (if it exists). - * @param {boolean=} show Whether to show the back button. - * @returns {boolean} Whether the back button is shown. - */ - 'showBackButton', - /** - * @ngdoc method - * @name $ionicNavBarDelegate#showBar - * @description - * Set/get whether the {@link ionic.directive:ionNavBar} is shown. - * @param {boolean} show Whether to show the bar. - * @returns {boolean} Whether the bar is shown. - */ - 'showBar', - /** - * @ngdoc method - * @name $ionicNavBarDelegate#setTitle - * @description - * Set the title for the {@link ionic.directive:ionNavBar}. - * @param {string} title The new title to show. - */ - 'setTitle', - /** - * @ngdoc method - * @name $ionicNavBarDelegate#changeTitle - * @description - * Change the title, transitioning the new title in and the old one out in a given direction. - * @param {string} title The new title to show. - * @param {string} direction The direction to transition the new title in. - * Available: 'forward', 'back'. - */ - 'changeTitle', - /** - * @ngdoc method - * @name $ionicNavBarDelegate#getTitle - * @returns {string} The current title of the navbar. - */ - 'getTitle', - /** - * @ngdoc method - * @name $ionicNavBarDelegate#getPreviousTitle - * @returns {string} The previous title of the navbar. - */ - 'getPreviousTitle' - /** - * @ngdoc method - * @name $ionicNavBarDelegate#$getByHandle - * @param {string} handle - * @returns `delegateInstance` A delegate instance that controls only the - * navBars with delegate-handle matching the given handle. - * - * Example: `$ionicNavBarDelegate.$getByHandle('myHandle').setTitle('newTitle')` - */ -])) - -.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('

')($scope); - angular.element(currentTitles[0]).replaceWith(oldTitleEl); - } - //Compile new title - newTitleEl = $compile('

')($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'); - }); - }); - }; -}]) - -/** - * @ngdoc directive - * @name ionNavBar - * @module ionic - * @delegate ionic.service:$ionicNavBarDelegate - * @restrict E - * - * @description - * If we have an {@link ionic.directive:ionNavView} directive, we can also create an - * ``, which will create a topbar that updates as the application state changes. - * - * We can add a back button by putting an {@link ionic.directive:ionNavBackButton} inside. - * - * 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') - * - * @usage - * - * ```html - * - * - * - * - * - * - * - * - * ``` - * - * @param {string=} delegate-handle The handle used to identify this navBar - * with {@link ionic.service:$ionicNavBarDelegate}. - * @param align-title {string=} Where to align the title of the navbar. - * Available: 'left', 'right', 'center'. Defaults to 'center'. - */ -.directive('ionNavBar', ['$ionicViewService', '$rootScope', '$animate', '$compile', -function($ionicViewService, $rootScope, $animate, $compile) { - - return { - restrict: 'E', - controller: '$ionicNavBar', - scope: true, - compile: function(tElement, tAttrs) { - //We cannot transclude here because it breaks element.data() inheritance on compile - tElement - .addClass('bar bar-header nav-bar') - .append( - '
' + - '
' + - '

' + - '
' + - '
' - ); - - return { pre: prelink }; - function prelink($scope, $element, $attr, navBarCtrl) { - navBarCtrl._headerBarView = new ionic.views.HeaderBar({ - el: $element[0], - alignTitle: $attr.alignTitle || 'center' - }); - - //defaults - $scope.backButtonShown = false; - $scope.shouldAnimate = true; - $scope.isReverse = false; - $scope.isInvisible = true; - - $scope.$on('$destroy', function() { - $scope.$parent.$hasHeader = false; - }); - - $scope.$watch(function() { - return ($scope.isReverse ? ' reverse' : '') + - ($scope.isInvisible ? ' invisible' : '') + - (!$scope.shouldAnimate ? ' no-animation' : ''); - }, function(className, oldClassName) { - $element.removeClass(oldClassName); - $element.addClass(className); - }); - - } - } - }; -}]) - -/** - * @ngdoc directive - * @name ionNavBackButton - * @module ionic - * @restrict E - * @parent ionNavBar - * @description - * Creates a back button inside an {@link ionic.directive:ionNavBar}. - * - * Will show up when the user is able to go back in the current navigation stack. - * - * By default, will go back when clicked. If you wish for more advanced behavior, see the - * examples below. - * - * @usage - * - * With default click action: - * - * ```html - * - * - * Back! - * - * - * ``` - * - * With custom click action, using {@link ionic.service:$ionicNavBarDelegate}: - * - * ```html - * - * - * Back - * - * - * ``` - * ```js - * function MyCtrl($scope, $ionicNavBarDelegate) { - * $scope.goBack = function() { - * $ionicNavBarDelegate.back(); - * }; - * } - * ``` - * - * Displaying the previous title on the back button, again using - * {@link ionic.service:$ionicNavBarDelegate}. - * - * ```html - * - * - * {% raw %}{{getPreviousTitle() || 'Back'}}{% endraw %} - * - * - * ``` - * ```js - * function MyCtrl($scope, $ionicNavBarDelegate) { - * $scope.getPreviousTitle = function() { - * return $ionicNavBarDelegate.getPreviousTitle(); - * }; - * } - * ``` - */ -.directive('ionNavBackButton', [ - '$ionicNgClick', - '$animate', -function($ionicNgClick, $animate) { - return { - restrict: 'E', - require: '^ionNavBar', - compile: function(tElement, tAttrs) { - tElement.addClass('button back-button ng-hide'); - return function($scope, $element, $attr, navBarCtrl) { - if (!$attr.ngClick) { - $scope.$navBack = navBarCtrl.back; - $ionicNgClick($scope, $element, '$navBack($event)'); - } - - //If the current viewstate does not allow a back button, - //always hide it. - var deregisterListener = $scope.$parent.$on( - '$viewHistory.historyChange', - function(e, data) { - $scope.hasBackButton = !!data.showBack; - } - ); - $scope.$on('$destroy', deregisterListener); - - //Make sure both that a backButton is allowed in the first place, - //and that it is shown by the current view. - $scope.$watch('!!(backButtonShown && hasBackButton)', ionic.animationFrameThrottle(function(show) { - if (show) $animate.removeClass($element, 'ng-hide'); - else $animate.addClass($element, 'ng-hide'); - })); - }; - } - }; -}]) - -/** - * @ngdoc directive - * @name ionNavButtons - * @module ionic - * @restrict E - * @parent ionNavView - * - * @description - * Use ionNavButtons to set the buttons on your {@link ionic.directive:ionNavBar} - * from within an {@link ionic.directive:ionView}. - * - * Any buttons you declare will be placed onto the navbar's corresponding side, - * and then destroyed when the user leaves their parent view. - * - * @usage - * ```html - * - * - * - * - * - * - * - * - * Some super content here! - * - * - * - * ``` - * - * @param {string} side The side to place the buttons on in the parent - * {@link ionic.directive:ionNavBar}. Available: 'left' or 'right'. - */ -.directive('ionNavButtons', ['$compile', '$animate', function($compile, $animate) { - return { - require: '^ionNavBar', - restrict: 'E', - compile: function($element, $attrs) { - var content = $element.contents().remove(); - return function($scope, $element, $attrs, navBarCtrl) { - var navElement = $attrs.side === 'right' ? - navBarCtrl.rightButtonsElement : - navBarCtrl.leftButtonsElement; - - //Put all of our inside buttons into their own span, - //so we can remove them all when this element dies - - //even if the buttons have changed through an ng-repeat or the like, - //we just remove their div parent and they are gone. - var buttons = angular.element('').append(content); - - //Compile buttons inside content so they have access to everything - //something inside content does (eg parent ionicScroll) - $element.append(buttons); - $compile(buttons)($scope); - - //Append buttons to navbar - $animate.enter(buttons, navElement); - - //When our ion-nav-buttons container is destroyed, - //destroy everything in the navbar - $scope.$on('$destroy', function() { - $animate.leave(buttons); - }); - - // The original element is just a completely empty element. - // make it invisible just to be sure it doesn't change any layout - $element.css('display', 'none'); - }; - } - }; -}]); diff --git a/js/ext/angular/src/directive/ionicRadio.js b/js/ext/angular/src/directive/ionicRadio.js deleted file mode 100644 index 9cc7576d27..0000000000 --- a/js/ext/angular/src/directive/ionicRadio.js +++ /dev/null @@ -1,130 +0,0 @@ -(function(ionic) { -'use strict'; - -angular.module('ionic.ui.radio', []) - -/** - * @ngdoc directive - * @name ionRadio - * @module ionic - * @restrict E - * @codepen saoBG - * @description - * The radio directive is no different than the HTML radio input, except it's styled differently. - * - * Radio behaves like any [AngularJS radio](http://docs.angularjs.org/api/ng/input/input[radio]). - * - * @usage - * ```html - * Choose A - * Choose B - * Choose C - * ``` - */ -.directive('ionRadio', function() { - return { - restrict: 'E', - replace: true, - require: '?ngModel', - scope: { - ngModel: '=?', - ngValue: '=?', - ngChange: '&', - icon: '@' - }, - transclude: true, - template: '', - - compile: function(element, attr) { - if(attr.name) element.children().eq(0).attr('name', attr.name); - if(attr.icon) element.children().eq(2).removeClass('ion-checkmark').addClass(attr.icon); - } - }; -}) - -// The radio button is a radio powered element with only -// one possible selection in a set of options. -.directive('ionRadioButtons', function() { - return { - restrict: 'E', - replace: true, - require: '?ngModel', - scope: { - value: '@' - }, - transclude: true, - template: '
', - - controller: ['$scope', '$element', function($scope, $element) { - - this.select = function(element) { - var c, children = $element.children(); - for(var i = 0; i < children.length; i++) { - c = children[i]; - if(c != element[0]) { - c.classList.remove('active'); - } - } - }; - - }], - - link: function($scope, $element, $attr, ngModel) { - var radio; - - if(ngModel) { - //$element.bind('tap', tapHandler); - - ngModel.$render = function() { - var children = $element.children(); - for(var i = 0; i < children.length; i++) { - children[i].classList.remove('active'); - } - $scope.$parent.$broadcast('radioButton.select', ngModel.$viewValue); - }; - } - } - }; -}) - -.directive('ionButtonRadio', function() { - return { - restrict: 'CA', - require: ['?^ngModel', '?^ionRadioButtons'], - link: function($scope, $element, $attr, ctrls) { - var ngModel = ctrls[0]; - var radioButtons = ctrls[1]; - if(!ngModel || !radioButtons) { return; } - - var setIt = function() { - $element.addClass('active'); - ngModel.$setViewValue($scope.$eval($attr.ngValue)); - - radioButtons.select($element); - }; - - var clickHandler = function(e) { - setIt(); - }; - - $scope.$on('radioButton.select', function(e, val) { - if(val == $scope.$eval($attr.ngValue)) { - $element.addClass('active'); - } - }); - - ionic.on('tap', clickHandler, $element[0]); - - $scope.$on('$destroy', function() { - ionic.off('tap', clickHandler); - }); - } - }; -}); - -})(window.ionic); diff --git a/js/ext/angular/src/directive/ionicSideMenu.js b/js/ext/angular/src/directive/ionicSideMenu.js deleted file mode 100644 index 9c86f4c464..0000000000 --- a/js/ext/angular/src/directive/ionicSideMenu.js +++ /dev/null @@ -1,465 +0,0 @@ -(function() { -'use strict'; - -/** - * @description - * The sideMenuCtrl lets you quickly have a draggable side - * left and/or right menu, which a center content area. - */ - -angular.module('ionic.ui.sideMenu', ['ionic.service.gesture', 'ionic.service.view']) - -/** - * The internal controller for the side menu controller. This - * extends our core Ionic side menu controller and exposes - * some side menu stuff on the current scope. - */ - -.run(['$ionicViewService', function($ionicViewService) { - // set that the side-menus directive should not animate when transitioning to it - $ionicViewService.disableRegisterByTagName('ion-side-menus'); -}]) - -/** - * @ngdoc service - * @name $ionicSideMenuDelegate - * @module ionic - * - * @description - * Delegate for controlling the {@link ionic.directive:ionSideMenus} directive. - * - * Methods called directly on the $ionicSideMenuDelegate service will control all side - * menus. Use the {@link ionic.service:$ionicSideMenuDelegate#$getByHandle $getByHandle} - * method to control specific ionSideMenus instances. - * - * @usage - * - * ```html - * - * - * - * Content! - * - * - * - * Left Menu! - * - * - * - * ``` - * ```js - * function MainCtrl($scope, $ionicSideMenuDelegate) { - * $scope.toggleLeftSideMenu = function() { - * $ionicSideMenuDelegate.toggleLeft(); - * }; - * } - * ``` - */ -.service('$ionicSideMenuDelegate', delegateService([ - /** - * @ngdoc method - * @name $ionicSideMenuDelegate#toggleLeft - * @description Toggle the left side menu (if it exists). - * @param {boolean=} isOpen Whether to open or close the menu. - * Default: Toggles the menu. - */ - 'toggleLeft', - /** - * @ngdoc method - * @name $ionicSideMenuDelegate#toggleRight - * @description Toggle the right side menu (if it exists). - * @param {boolean=} isOpen Whether to open or close the menu. - * Default: Toggles the menu. - */ - 'toggleRight', - /** - * @ngdoc method - * @name $ionicSideMenuDelegate#getOpenRatio - * @description Gets the ratio of open amount over menu width. For example, a - * menu of width 100 that is opened by 50 pixels is 50% opened, and would return - * a ratio of 0.5. - * - * @returns {float} 0 if nothing is open, between 0 and 1 if left menu is - * opened/opening, and between 0 and -1 if right menu is opened/opening. - */ - 'getOpenRatio', - /** - * @ngdoc method - * @name $ionicSideMenuDelegate#isOpen - * @returns {boolean} Whether either the left or right menu is currently opened. - */ - 'isOpen', - /** - * @ngdoc method - * @name $ionicSideMenuDelegate#isOpenLeft - * @returns {boolean} Whether the left menu is currently opened. - */ - 'isOpenLeft', - /** - * @ngdoc method - * @name $ionicSideMenuDelegate#isOpenRight - * @returns {boolean} Whether the right menu is currently opened. - */ - 'isOpenRight', - /** - * @ngdoc method - * @name $ionicSideMenuDelegate#canDragContent - * @param {boolean=} canDrag Set whether the content can or cannot be dragged to open - * side menus. - * @returns {boolean} Whether the content can be dragged to open side menus. - */ - 'canDragContent' - /** - * @ngdoc method - * @name $ionicSideMenuDelegate#$getByHandle - * @param {string} handle - * @returns `delegateInstance` A delegate instance that controls only the - * {@link ionic.directive:ionSideMenus} directives with `delegate-handle` matching - * the given handle. - * - * Example: `$ionicSideMenuDelegate.$getByHandle('my-handle').toggleLeft();` - */ -])) - -/** - * @ngdoc directive - * @name ionSideMenus - * @module ionic - * @delegate ionic.service:$ionicSideMenuDelegate - * @restrict E - * - * @description - * A container element for side menu(s) and the main content. Allows the left - * and/or right side menu to be toggled by dragging the main content area side - * to side. - * - * ![Side Menu](http://ionicframework.com.s3.amazonaws.com/docs/controllers/sidemenu.gif) - * - * For more information on side menus, check out the documenation for - * {@link ionic.directive:ionSideMenuContent} and - * {@link ionic.directive:ionSideMenu}. - * - * @usage - * To use side menus, add an `` parent element, - * an `` for the center content, - * and one or more `` directives. - * - * ```html - * - * - * - * - * - * - * - * - * - * - * - * - * - * ``` - * ```js - * function ContentController($scope, $ionicSideMenuDelegate) { - * $scope.toggleLeft = function() { - * $ionicSideMenuDelegate.toggleLeft(); - * }; - * } - * ``` - * - * @param {string=} delegate-handle The handle used to identify this side menu - * with {@link ionic.service:$ionicSideMenuDelegate}. - * - */ -.directive('ionSideMenus', function() { - return { - restrict: 'ECA', - controller: ['$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); - }], - replace: true, - transclude: true, - template: '
' - }; -}) - -/** - * @ngdoc directive - * @name ionSideMenuContent - * @module ionic - * @restrict E - * @parent ionic.directive:ionSideMenus - * - * @description - * A container for the main visible content, sibling to one or more - * {@link ionic.directive:ionSideMenu} directives. - * - * @usage - * ```html - * - * - * ``` - * For a complete side menu example, see the - * {@link ionic.directive:ionSideMenus} documentation. - * - * @param {boolean=} drag-content Whether the content can be dragged. Default true. - * - */ -.directive('ionSideMenuContent', ['$timeout', '$ionicGesture', function($timeout, $ionicGesture) { - - return { - restrict: 'EA', //DEPRECATED 'A' - require: '^ionSideMenus', - scope: true, - compile: function(element, attr) { - return { pre: prelink }; - function prelink($scope, $element, $attr, sideMenuCtrl) { - - $element.addClass('menu-content pane'); - - if (angular.isDefined(attr.dragContent)) { - $scope.$watch(attr.dragContent, function(value) { - sideMenuCtrl.canDragContent(value); - }); - } else { - sideMenuCtrl.canDragContent(true); - } - - var defaultPrevented = false; - var isDragging = false; - - // Listen for taps on the content to close the menu - function contentTap(e) { - if(sideMenuCtrl.getOpenAmount() !== 0) { - sideMenuCtrl.close(); - e.gesture.srcEvent.preventDefault(); - } - } - ionic.on('tap', contentTap, $element[0]); - - var dragFn = function(e) { - if(defaultPrevented || !sideMenuCtrl.isDraggableTarget(e)) return; - isDragging = true; - sideMenuCtrl._handleDrag(e); - e.gesture.srcEvent.preventDefault(); - }; - - var dragVertFn = function(e) { - if(isDragging) { - e.gesture.srcEvent.preventDefault(); - } - }; - - //var dragGesture = Gesture.on('drag', dragFn, $element); - var dragRightGesture = $ionicGesture.on('dragright', dragFn, $element); - var dragLeftGesture = $ionicGesture.on('dragleft', dragFn, $element); - var dragUpGesture = $ionicGesture.on('dragup', dragVertFn, $element); - var dragDownGesture = $ionicGesture.on('dragdown', dragVertFn, $element); - - var dragReleaseFn = function(e) { - isDragging = false; - if(!defaultPrevented) { - sideMenuCtrl._endDrag(e); - } - defaultPrevented = false; - }; - - var releaseGesture = $ionicGesture.on('release', dragReleaseFn, $element); - - sideMenuCtrl.setContent({ - onDrag: function(e) {}, - endDrag: function(e) {}, - getTranslateX: function() { - return $scope.sideMenuContentTranslateX || 0; - }, - setTranslateX: ionic.animationFrameThrottle(function(amount) { - $element[0].style[ionic.CSS.TRANSFORM] = 'translate3d(' + amount + 'px, 0, 0)'; - $timeout(function() { - $scope.sideMenuContentTranslateX = amount; - }); - }), - enableAnimation: function() { - //this.el.classList.add(this.animateClass); - $scope.animationEnabled = true; - $element[0].classList.add('menu-animated'); - }, - disableAnimation: function() { - //this.el.classList.remove(this.animateClass); - $scope.animationEnabled = false; - $element[0].classList.remove('menu-animated'); - } - }); - - // Cleanup - $scope.$on('$destroy', function() { - $ionicGesture.off(dragLeftGesture, 'dragleft', dragFn); - $ionicGesture.off(dragRightGesture, 'dragright', dragFn); - $ionicGesture.off(dragUpGesture, 'dragup', dragFn); - $ionicGesture.off(dragDownGesture, 'dragdown', dragFn); - $ionicGesture.off(releaseGesture, 'release', dragReleaseFn); - ionic.off('tap', contentTap, $element[0]); - }); - } - } - }; -}]) - -/** - * @ngdoc directive - * @name ionSideMenu - * @module ionic - * @restrict E - * @parent ionic.directive:ionSideMenus - * - * @description - * A container for a side menu, sibling to an {@link ionic.directive:ionSideMenuContent} directive. - * - * @usage - * ```html - * - * - * ``` - * For a complete side menu example, see the - * {@link ionic.directive:ionSideMenus} documentation. - * - * @param {string} side Which side the side menu is currently on. Allowed values: 'left' or 'right'. - * @param {boolean=} is-enabled Whether this side menu is enabled. - * @param {number=} width How many pixels wide the side menu should be. Defaults to 275. - */ -.directive('ionSideMenu', function() { - return { - restrict: 'E', - require: '^ionSideMenus', - scope: true, - compile: function(element, attr) { - angular.isUndefined(attr.isEnabled) && attr.$set('isEnabled', 'true'); - angular.isUndefined(attr.width) && attr.$set('width', '275'); - - element.addClass('menu menu-' + attr.side); - - return function($scope, $element, $attr, sideMenuCtrl) { - $scope.side = $attr.side || 'left'; - - var sideMenu = sideMenuCtrl[$scope.side] = new ionic.views.SideMenu({ - width: 275, - el: $element[0], - isEnabled: true - }); - - $scope.$watch($attr.width, function(val) { - var numberVal = +val; - if (numberVal && numberVal == val) { - sideMenu.setWidth(+val); - } - }); - $scope.$watch($attr.isEnabled, function(val) { - sideMenu.setIsEnabled(!!val); - }); - }; - } - }; -}) - -/** - * @ngdoc directive - * @name menuToggle - * @module ionic - * @restrict AC - * - * @description - * Toggle a side menu on the given side - * - * @usage - * Below is an example of a link within a nav bar. Tapping this link would - * automatically open the given side menu - * - * ```html - * - * - * - * - * ... - * - * ``` - */ -.directive('menuToggle', ['$ionicViewService', function($ionicViewService) { - return { - restrict: 'AC', - require: '^ionSideMenus', - link: function($scope, $element, $attr, sideMenuCtrl) { - var side = $attr.menuToggle || 'left'; - $element.bind('click', function(){ - if(side === 'left') { - sideMenuCtrl.toggleLeft(); - } else if(side === 'right') { - sideMenuCtrl.toggleRight(); - } - }); - } - }; -}]) - -/** - * @ngdoc directive - * @name menuClose - * @module ionic - * @restrict AC - * - * @description - * Closes a side menu which is currently opened. - * - * @usage - * Below is an example of a link within a side menu. Tapping this link would - * automatically close the currently opened menu - * - * ```html - * Home - * ``` - */ -.directive('menuClose', ['$ionicViewService', function($ionicViewService) { - return { - restrict: 'AC', - require: '^ionSideMenus', - link: function($scope, $element, $attr, sideMenuCtrl) { - $element.bind('click', function(){ - sideMenuCtrl.close(); - }); - } - }; -}]); - -})(); diff --git a/js/ext/angular/src/directive/ionicTabBar.js b/js/ext/angular/src/directive/ionicTabBar.js deleted file mode 100644 index 36042c2ebc..0000000000 --- a/js/ext/angular/src/directive/ionicTabBar.js +++ /dev/null @@ -1,454 +0,0 @@ -angular.module('ionic.ui.tabs', ['ionic.service.view']) - -.run(['$ionicViewService', function($ionicViewService) { - // set that the tabs directive should not animate when transitioning - // to it. Instead, the children directives would animate - $ionicViewService.disableRegisterByTagName('ion-tabs'); -}]) - -/** - * @ngdoc service - * @name $ionicTabsDelegate - * @module ionic - * - * @description - * Delegate for controlling the {@link ionic.directive:ionTabs} directive. - * - * Methods called directly on the $ionicTabsDelegate service will control all ionTabs - * directives. Use the {@link ionic.service:$ionicTabsDelegate#$getByHandle $getByHandle} - * method to control specific ionTabs instances. - * - * @usage - * - * ```html - * - * - * - * - * Hello tab 1! - * - * - * Hello tab 2! - * - * - * - * ``` - * ```js - * function MyCtrl($scope, $ionicTabsDelegate) { - * $scope.selectTabWithIndex = function(index) { - * $ionicTabsDelegate.select(index); - * } - * } - * ``` - */ -.service('$ionicTabsDelegate', delegateService([ - /** - * @ngdoc method - * @name $ionicTabsDelegate#select - * @description Select the tab matching the given index. - * - * @param {number} index Index of the tab to select. - * @param {boolean=} shouldChangeHistory Whether this selection should load this tab's - * view history (if it exists) and use it, or just load the default page. - * Default false. - * Hint: you probably want this to be true if you have an - * {@link ionic.directive:ionNavView} inside your tab. - */ - 'select', - /** - * @ngdoc method - * @name $ionicTabsDelegate#selectedIndex - * @returns `number` The index of the selected tab, or -1. - */ - 'selectedIndex' - /** - * @ngdoc method - * @name $ionicTabsDelegate#$getByHandle - * @param {string} handle - * @returns `delegateInstance` A delegate instance that controls only the - * {@link ionic.directive:ionTabs} directives with `delegate-handle` matching - * the given handle. - * - * Example: `$ionicTabsDelegate.$getByHandle('my-handle').select(0);` - */ -])) - -.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); - } - } - }; -}]) - -/** - * @ngdoc directive - * @name ionTabs - * @module ionic - * @delegate ionic.service:$ionicTabsDelegate - * @restrict E - * @codepen KbrzJ - * - * @description - * Powers a multi-tabbed interface with a Tab Bar and a set of "pages" that can be tabbed - * through. - * - * Assign any [tabs class](/docs/components#tabs) or - * [animation class](/docs/components#animation) to the element to define - * its look and feel. - * - * See the {@link ionic.directive:ionTab} directive's documentation for more details on - * individual tabs. - * - * @usage - * ```html - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * ``` - * - * @param {string=} delegate-handle The handle used to identify these tabs - * with {@link ionic.service:$ionicTabsDelegate}. - */ - -.directive('ionTabs', ['$ionicViewService', '$ionicTabsDelegate', function($ionicViewService, $ionicTabsDelegate) { - return { - restrict: 'E', - scope: true, - controller: 'ionicTabs', - compile: function(element, attr) { - element.addClass('view'); - //We cannot use regular transclude here because it breaks element.data() - //inheritance on compile - var innerElement = angular.element('
'); - innerElement.append(element.contents()); - element.append(innerElement); - - return { pre: prelink }; - function prelink($scope, $element, $attr, tabsCtrl) { - var deregisterInstance = $ionicTabsDelegate._registerInstance( - tabsCtrl, $attr.delegateHandle - ); - - $scope.$on('$destroy', deregisterInstance); - - tabsCtrl.$scope = $scope; - tabsCtrl.$element = $element; - tabsCtrl.$tabsElement = angular.element($element[0].querySelector('.tabs')); - - var el = $element[0]; - $scope.$watch(function() { return el.className; }, function(value) { - var isTabsTop = value.indexOf('tabs-top') !== -1; - var isHidden = value.indexOf('tabs-item-hide') !== -1; - $scope.$hasTabs = !isTabsTop && !isHidden; - $scope.$hasTabsTop = isTabsTop && !isHidden; - }); - $scope.$on('$destroy', function() { - $scope.$hasTabs = $scope.$hasTabsTop = null; - }); - } - } - }; -}]) - -.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(); - }; -}]) - -/** - * @ngdoc directive - * @name ionTab - * @module ionic - * @restrict E - * @parent ionic.directive:ionTabs - * - * @description - * Contains a tab's content. The content only exists while the given tab is selected. - * - * Each ionTab has its own view history. - * - * @usage - * ```html - * - * - * ``` - * For a complete, working tab bar example, see the {@link ionic.directive:ionTabs} documentation. - * - * @param {string} title The title of the tab. - * @param {string=} href The link that this tab will navigate to when tapped. - * @param {string=} icon The icon of the tab. If given, this will become the default for icon-on and icon-off. - * @param {string=} icon-on The icon of the tab while it is selected. - * @param {string=} icon-off The icon of the tab while it is not selected. - * @param {expression=} badge The badge to put on this tab (usually a number). - * @param {expression=} badge-style The style of badge to put on this tab (eg tabs-positive). - * @param {expression=} on-select Called when this tab is selected. - * @param {expression=} on-deselect Called when this tab is deselected. - * @param {expression=} ng-click By default, the tab will be selected on click. If ngClick is set, it will not. You can explicitly switch tabs using {@link ionic.service:$ionicTabsDelegate#select $ionicTabsDelegate.select()}. - */ -.directive('ionTab', ['$rootScope', '$animate', '$ionicBind', '$compile', '$ionicViewService', '$state', '$location', -function($rootScope, $animate, $ionicBind, $compile, $ionicViewService, $state, $location) { - - //Returns ' key="value"' if value exists - function attrStr(k,v) { - return angular.isDefined(v) ? ' ' + k + '="' + v + '"' : ''; - } - return { - restrict: 'E', - require: ['^ionTabs', 'ionTab'], - replace: true, - controller: 'ionicTab', - scope: true, - compile: function(element, attr) { - var navView = element[0].querySelector('ion-nav-view') || - element[0].querySelector('data-ion-nav-view'); - var navViewName = navView && navView.getAttribute('name'); - - - //We create the tabNavElement in the compile phase so that the - //attributes we pass down won't be interpolated yet - we want - //to pass down the 'raw' versions of the attributes - var tabNavElement = angular.element( - '' - ); - - //Remove the contents of the element so we can compile them later, if tab is selected - //We don't use regular transclusion because it breaks element inheritance - var tabContent = angular.element('
') - .append( element.contents().remove() ); - - return function link($scope, $element, $attr, ctrls) { - var childScope; - var childElement; - var tabsCtrl = ctrls[0]; - var tabCtrl = ctrls[1]; - - $ionicBind($scope, $attr, { - animate: '=', - onSelect: '&', - onDeselect: '&', - title: '@', - uiSref: '@', - href: '@', - }); - - tabsCtrl.add($scope); - $scope.$on('$destroy', function() { - tabsCtrl.remove($scope); - tabNavElement.isolateScope().$destroy(); - tabNavElement.remove(); - }); - - //Remove title attribute so browser-tooltip does not apear - $element[0].removeAttribute('title'); - - if (navViewName) { - tabCtrl.navViewName = navViewName; - } - $scope.$on('$stateChangeSuccess', selectIfMatchesState); - selectIfMatchesState(); - function selectIfMatchesState() { - if (tabCtrl.tabMatchesState()) { - tabsCtrl.select($scope); - } - } - - tabNavElement.data('$ionTabsController', tabsCtrl); - tabNavElement.data('$ionTabController', tabCtrl); - tabsCtrl.$tabsElement.append($compile(tabNavElement)($scope)); - - $scope.$watch('$tabSelected', function(value) { - childScope && childScope.$destroy(); - childScope = null; - childElement && $animate.leave(childElement); - childElement = null; - if (value) { - childScope = $scope.$new(); - childElement = tabContent.clone(); - $animate.enter(childElement, tabsCtrl.$element); - $compile(childElement)(childScope); - } - }); - - }; - } - }; -}]) - -.directive('ionTabNav', ['$ionicNgClick', function($ionicNgClick) { - return { - restrict: 'E', - replace: true, - require: ['^ionTabs', '^ionTab'], - template: - '' + - '{{badge}}' + - '' + - '' + - '' + - '', - scope: { - title: '@', - icon: '@', - iconOn: '@', - iconOff: '@', - badge: '=', - badgeStyle: '@' - }, - compile: function(element, attr, transclude) { - return function link($scope, $element, $attrs, ctrls) { - var tabsCtrl = ctrls[0], - tabCtrl = ctrls[1]; - - //Remove title attribute so browser-tooltip does not apear - $element[0].removeAttribute('title'); - - $scope.selectTab = function(e) { - e.preventDefault(); - tabsCtrl.select(tabCtrl.$scope, true); - }; - if (!$attrs.ngClick) { - $ionicNgClick($scope, $element, 'selectTab($event)'); - } - - $scope.getIconOn = function() { - return $scope.iconOn || $scope.icon; - }; - $scope.getIconOff = function() { - return $scope.iconOff || $scope.icon; - }; - - $scope.isTabActive = function() { - return tabsCtrl.selectedTab() === tabCtrl.$scope; - }; - }; - } - }; -}]); diff --git a/js/ext/angular/src/directive/ionicVirtRepeat.js b/js/ext/angular/src/directive/ionicVirtRepeat.js deleted file mode 100644 index 9418e131f4..0000000000 --- a/js/ext/angular/src/directive/ionicVirtRepeat.js +++ /dev/null @@ -1,24 +0,0 @@ -/* -(function() { -'use strict'; - -angular.module('ionic.ui.virtRepeat', []) - -.directive('ionVirtRepeat', function() { - return { - require: ['?ngModel', '^virtualList'], - transclude: 'element', - priority: 1000, - terminal: true, - compile: function(element, attr, transclude) { - return function($scope, $element, $attr, ctrls) { - var virtualList = ctrls[1]; - - virtualList.listView.renderViewport = function(high, low, start, end) { - }; - }; - } - }; -}); -})(ionic); -*/ diff --git a/js/ext/angular/src/directive/ionicVirtualRepeat.js b/js/ext/angular/src/directive/ionicVirtualRepeat.js deleted file mode 100644 index d3797a8c73..0000000000 --- a/js/ext/angular/src/directive/ionicVirtualRepeat.js +++ /dev/null @@ -1,328 +0,0 @@ -/* -(function() { -'use strict'; - -// Turn the expression supplied to the directive: -// -// a in b -// -// into `{ value: "a", collection: "b" }` -function parseRepeatExpression(expression){ - var match = expression.match(/^\s*([\$\w]+)\s+in\s+(\S*)\s*$/); - if (! match) { - throw new Error("Expected sfVirtualRepeat in form of '_item_ in _collection_' but got '" + - expression + "'."); - } - return { - value: match[1], - collection: match[2] - }; -} - -// Utility to filter out elements by tag name -function isTagNameInList(element, list){ - var t, tag = element.tagName.toUpperCase(); - for( t = 0; t < list.length; t++ ){ - if( list[t] === tag ){ - return true; - } - } - return false; -} - - -// Utility to find the viewport/content elements given the start element: -function findViewportAndContent(startElement){ - var root = $rootElement[0]; - var e, n; - // Somewhere between the grandparent and the root node - for( e = startElement.parent().parent()[0]; e !== root; e = e.parentNode ){ - // is an element - if( e.nodeType != 1 ) break; - // that isn't in the blacklist (tables etc.), - if( isTagNameInList(e, DONT_WORK_AS_VIEWPORTS) ) continue; - // has a single child element (the content), - if( e.childElementCount != 1 ) continue; - // which is not in the blacklist - if( isTagNameInList(e.firstElementChild, DONT_WORK_AS_CONTENT) ) continue; - // and no text. - for( n = e.firstChild; n; n = n.nextSibling ){ - if( n.nodeType == 3 && /\S/g.test(n.textContent) ){ - break; - } - } - if( n === null ){ - // That element should work as a viewport. - return { - viewport: angular.element(e), - content: angular.element(e.firstElementChild) - }; - } - } - throw new Error("No suitable viewport element"); -} - -// Apply explicit height and overflow styles to the viewport element. -// -// If the viewport has a max-height (inherited or otherwise), set max-height. -// Otherwise, set height from the current computed value or use -// window.innerHeight as a fallback -// -function setViewportCss(viewport){ - var viewportCss = {'overflow': 'auto'}, - style = window.getComputedStyle ? - window.getComputedStyle(viewport[0]) : - viewport[0].currentStyle, - maxHeight = style && style.getPropertyValue('max-height'), - height = style && style.getPropertyValue('height'); - - if( maxHeight && maxHeight !== '0px' ){ - viewportCss.maxHeight = maxHeight; - }else if( height && height !== '0px' ){ - viewportCss.height = height; - }else{ - viewportCss.height = window.innerHeight; - } - viewport.css(viewportCss); -} - -// Apply explicit styles to the content element to prevent pesky padding -// or borders messing with our calculations: -function setContentCss(content){ - var contentCss = { - margin: 0, - padding: 0, - border: 0, - 'box-sizing': 'border-box' - }; - content.css(contentCss); -} - -// TODO: compute outerHeight (padding + border unless box-sizing is border) -function computeRowHeight(element){ - var style = window.getComputedStyle ? window.getComputedStyle(element) - : element.currentStyle, - maxHeight = style && style.getPropertyValue('max-height'), - height = style && style.getPropertyValue('height'); - - if( height && height !== '0px' && height !== 'auto' ){ - $log.info('Row height is "%s" from css height', height); - }else if( maxHeight && maxHeight !== '0px' && maxHeight !== 'none' ){ - height = maxHeight; - $log.info('Row height is "%s" from css max-height', height); - }else if( element.clientHeight ){ - height = element.clientHeight+'px'; - $log.info('Row height is "%s" from client height', height); - }else{ - throw new Error("Unable to compute height of row"); - } - angular.element(element).css('height', height); - return parseInt(height, 10); -} - -angular.module('ionic.ui.virtualRepeat', []) - -// -// A replacement for ng-repeat that supports virtual lists. -// This is not a 1 to 1 replacement for ng-repeat. However, in situations -// where you have huge lists, this repeater will work with our virtual -// scrolling to only render items that are showing or will be showing -// if a scroll is made. -// -.directive('ionVirtualRepeat', ['$log', function($log) { - return { - require: ['?ngModel, ^virtualList'], - transclude: 'element', - priority: 1000, - terminal: true, - compile: function(element, attr, transclude) { - var ident = parseRepeatExpression(attr.sfVirtualRepeat); - - return function(scope, iterStartElement, attrs, ctrls, b) { - var virtualList = ctrls[1]; - - var rendered = []; - var rowHeight = 0; - var sticky = false; - - var dom = virtualList.element; - //var dom = findViewportAndContent(iterStartElement); - - // The list structure is controlled by a few simple (visible) variables: - var state = 'ngModel' in attrs ? scope.$eval(attrs.ngModel) : {}; - - function makeNewScope (idx, collection, containerScope) { - var childScope = containerScope.$new(); - childScope[ident.value] = collection[idx]; - childScope.$index = idx; - childScope.$first = (idx === 0); - childScope.$last = (idx === (collection.length - 1)); - childScope.$middle = !(childScope.$first || childScope.$last); - childScope.$watch(function updateChildScopeItem(){ - childScope[ident.value] = collection[idx]; - }); - return childScope; - } - - // Given the collection and a start and end point, add the current - function addElements (start, end, collection, containerScope, insPoint) { - var frag = document.createDocumentFragment(); - var newElements = [], element, idx, childScope; - for( idx = start; idx !== end; idx ++ ){ - childScope = makeNewScope(idx, collection, containerScope); - element = linker(childScope, angular.noop); - //setElementCss(element); - newElements.push(element); - frag.appendChild(element[0]); - } - insPoint.after(frag); - return newElements; - } - - function recomputeActive() { - // We want to set the start to the low water mark unless the current - // start is already between the low and high water marks. - var start = clip(state.firstActive, state.firstVisible - state.lowWater, state.firstVisible - state.highWater); - // Similarly for the end - var end = clip(state.firstActive + state.active, - state.firstVisible + state.visible + state.lowWater, - state.firstVisible + state.visible + state.highWater ); - state.firstActive = Math.max(0, start); - state.active = Math.min(end, state.total) - state.firstActive; - } - - function sfVirtualRepeatOnScroll(evt){ - if( !rowHeight ){ - return; - } - // Enter the angular world for the state change to take effect. - scope.$apply(function(){ - state.firstVisible = Math.floor(evt.target.scrollTop / rowHeight); - state.visible = Math.ceil(dom.viewport[0].clientHeight / rowHeight); - $log.log('scroll to row %o', state.firstVisible); - sticky = evt.target.scrollTop + evt.target.clientHeight >= evt.target.scrollHeight; - recomputeActive(); - $log.log(' state is now %o', state); - $log.log(' sticky = %o', sticky); - }); - } - - function sfVirtualRepeatWatchExpression(scope){ - var coll = scope.$eval(ident.collection); - if( coll.length !== state.total ){ - state.total = coll.length; - recomputeActive(); - } - return { - start: state.firstActive, - active: state.active, - len: coll.length - }; - } - - function destroyActiveElements (action, count) { - var dead, ii, remover = Array.prototype[action]; - for( ii = 0; ii < count; ii++ ){ - dead = remover.call(rendered); - dead.scope().$destroy(); - dead.remove(); - } - } - - // When the watch expression for the repeat changes, we may need to add - // and remove scopes and elements - function sfVirtualRepeatListener(newValue, oldValue, scope){ - var oldEnd = oldValue.start + oldValue.active, - collection = scope.$eval(ident.collection), - newElements; - if(newValue === oldValue) { - $log.info('initial listen'); - newElements = addElements(newValue.start, oldEnd, collection, scope, iterStartElement); - rendered = newElements; - if(rendered.length) { - rowHeight = computeRowHeight(newElements[0][0]); - } - } else { - var newEnd = newValue.start + newValue.active; - var forward = newValue.start >= oldValue.start; - var delta = forward ? newValue.start - oldValue.start - : oldValue.start - newValue.start; - var endDelta = newEnd >= oldEnd ? newEnd - oldEnd : oldEnd - newEnd; - var contiguous = delta < (forward ? oldValue.active : newValue.active); - $log.info('change by %o,%o rows %s', delta, endDelta, forward ? 'forward' : 'backward'); - if(!contiguous) { - $log.info('non-contiguous change'); - destroyActiveElements('pop', rendered.length); - rendered = addElements(newValue.start, newEnd, collection, scope, iterStartElement); - } else { - if(forward) { - $log.info('need to remove from the top'); - destroyActiveElements('shift', delta); - } else if(delta) { - $log.info('need to add at the top'); - newElements = addElements( - newValue.start, - oldValue.start, - collection, scope, iterStartElement); - rendered = newElements.concat(rendered); - } - - if(newEnd < oldEnd) { - $log.info('need to remove from the bottom'); - destroyActiveElements('pop', oldEnd - newEnd); - } else if(endDelta) { - var lastElement = rendered[rendered.length-1]; - $log.info('need to add to the bottom'); - newElements = addElements( - oldEnd, - newEnd, - collection, scope, lastElement); - rendered = rendered.concat(newElements); - } - } - if(!rowHeight && rendered.length) { - rowHeight = computeRowHeight(rendered[0][0]); - } - dom.content.css({'padding-top': newValue.start * rowHeight + 'px'}); - } - dom.content.css({'height': newValue.len * rowHeight + 'px'}); - if(sticky) { - dom.viewport[0].scrollTop = dom.viewport[0].clientHeight + dom.viewport[0].scrollHeight; - } - } - - // - The index of the first active element - state.firstActive = 0; - // - The index of the first visible element - state.firstVisible = 0; - // - The number of elements visible in the viewport. - state.visible = 0; - // - The number of active elements - state.active = 0; - // - The total number of elements - state.total = 0; - // - The point at which we add new elements - state.lowWater = state.lowWater || 100; - // - The point at which we remove old elements - state.highWater = state.highWater || 300; - // TODO: now watch the water marks - - setContentCss(dom.content); - setViewportCss(dom.viewport); - // When the user scrolls, we move the `state.firstActive` - dom.bind('momentumScrolled', sfVirtualRepeatOnScroll); - - scope.$on('$destroy', function () { - dom.unbind('momentumScrolled', sfVirtualRepeatOnScroll); - }); - - // The watch on the collection is just a watch on the length of the - // collection. We don't care if the content changes. - scope.$watch(sfVirtualRepeatWatchExpression, sfVirtualRepeatListener, true); - }; - } - }; - }]); - -})(ionic); -*/ diff --git a/js/ext/angular/src/ionicAngular.js b/js/ext/angular/src/ionicAngular.js deleted file mode 100644 index 4b15fa2872..0000000000 --- a/js/ext/angular/src/ionicAngular.js +++ /dev/null @@ -1,50 +0,0 @@ -/** - * Create a wrapping module to ease having to include too many - * modules. - */ - -/** - * @ngdoc module - * @name ionic - * @description - * Ionic main module. - */ - -angular.module('ionic.service', [ - 'ionic.service.bind', - 'ionic.service.platform', - 'ionic.service.actionSheet', - 'ionic.service.gesture', - 'ionic.service.loading', - 'ionic.service.modal', - 'ionic.service.popup', - 'ionic.service.templateLoad', - 'ionic.service.view', - 'ionic.decorator.location' -]); - -angular.module('ionic.ui', [ - 'ionic.ui.checkbox', - 'ionic.ui.content', - 'ionic.ui.header', - 'ionic.ui.list', - 'ionic.ui.navBar', - 'ionic.ui.radio', - 'ionic.ui.scroll', - 'ionic.ui.sideMenu', - 'ionic.ui.slideBox', - 'ionic.ui.tabs', - 'ionic.ui.toggle', - 'ionic.ui.touch', - 'ionic.ui.viewState' -]); - -angular.module('ionic', [ - 'ionic.service', - 'ionic.ui', - - // Angular deps - 'ngAnimate', - 'ngSanitize', - 'ui.router' -]); diff --git a/js/ext/angular/test/actionSheet.html b/js/ext/angular/test/actionSheet.html deleted file mode 100644 index 2ff5d42bf0..0000000000 --- a/js/ext/angular/test/actionSheet.html +++ /dev/null @@ -1,161 +0,0 @@ - - - - Action Sheet - - - - - - - - - -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - - -
- - - diff --git a/js/ext/angular/test/loading.html b/js/ext/angular/test/loading.html deleted file mode 100644 index 8b10017ea5..0000000000 --- a/js/ext/angular/test/loading.html +++ /dev/null @@ -1,29 +0,0 @@ - - - - Loading - - - - - - - - - - - - - - diff --git a/js/ext/angular/test/scroll.html b/js/ext/angular/test/scroll.html deleted file mode 100644 index 6842edd8f3..0000000000 --- a/js/ext/angular/test/scroll.html +++ /dev/null @@ -1,134 +0,0 @@ - - - - Content - - - - - - - - - - - - -

Hourly Forecast

- -
-
-
- - -
- -
- {{hour.temp}} °F -
-
-
-
- - Scroll to 100 - - -
-
-
-
- - - - - diff --git a/js/views/loadingView.js b/js/views/loadingView.js deleted file mode 100644 index 18b1ba52d7..0000000000 --- a/js/views/loadingView.js +++ /dev/null @@ -1,56 +0,0 @@ -(function(ionic) { -'use strict'; - /** - * Loading - * - * The Loading is an overlay that can be used to indicate - * activity while blocking user interaction. - */ - ionic.views.Loading = ionic.views.View.inherit({ - initialize: function(opts) { - var _this = this; - - this.el = opts.el; - - this.maxWidth = opts.maxWidth || 200; - - this.showDelay = opts.showDelay || 0; - - this._loadingBox = this.el.querySelector('.loading') || this.el; - }, - show: function() { - var _this = this; - - if(this._loadingBox) { - var lb = _this._loadingBox; - - var width = Math.min(_this.maxWidth, Math.max(window.outerWidth - 40, lb.offsetWidth)); - - lb.style.width = width + 'px'; - - lb.style.marginLeft = (-lb.offsetWidth) / 2 + 'px'; - lb.style.marginTop = (-lb.offsetHeight) / 2 + 'px'; - - // Wait 'showDelay' ms before showing the loading screen - this._showDelayTimeout = window.setTimeout(function() { - _this.el.classList.add('active'); - }, _this.showDelay); - } - }, - hide: function() { - // Force a reflow so the animation will actually run - this.el.offsetWidth; - - // Prevent unnecessary 'show' after 'hide' has already been called - window.clearTimeout(this._showDelayTimeout); - - this.el.classList.remove('active'); - }, - setContent: function(html) { - if (this._loadingBox) { - this._loadingBox.innerHTML = html || ''; - } - } - }); - -})(ionic); diff --git a/js/views/navBarView.js b/js/views/navBarView.js deleted file mode 100644 index 897fa76b1a..0000000000 --- a/js/views/navBarView.js +++ /dev/null @@ -1,53 +0,0 @@ -(function(ionic) { -'use strict'; - - ionic.views.NavBar = ionic.views.View.inherit({ - initialize: function(opts) { - this.el = opts.el; - - this._titleEl = this.el.querySelector('.title'); - - if(opts.hidden) { - this.hide(); - } - }, - hide: function() { - this.el.classList.add('hidden'); - }, - show: function() { - this.el.classList.remove('hidden'); - }, - shouldGoBack: function() {}, - - setTitle: function(title) { - if(!this._titleEl) { - return; - } - this._titleEl.innerHTML = title; - }, - - showBackButton: function(shouldShow) { - var _this = this; - - if(!this._currentBackButton) { - var back = document.createElement('a'); - back.className = 'button back'; - back.innerHTML = 'Back'; - - this._currentBackButton = back; - this._currentBackButton.onclick = function(event) { - _this.shouldGoBack && _this.shouldGoBack(); - }; - } - - if(shouldShow && !this._currentBackButton.parentNode) { - // Prepend the back button - this.el.insertBefore(this._currentBackButton, this.el.firstChild); - } else if(!shouldShow && this._currentBackButton.parentNode) { - // Remove the back button if it's there - this._currentBackButton.parentNode.removeChild(this._currentBackButton); - } - } - }); - -})(ionic); diff --git a/js/views/tabBarView.js b/js/views/tabBarView.js deleted file mode 100644 index 560995d3e8..0000000000 --- a/js/views/tabBarView.js +++ /dev/null @@ -1,224 +0,0 @@ -(function(ionic) { -'use strict'; - -ionic.views.TabBarItem = ionic.views.View.inherit({ - initialize: function(el) { - this.el = el; - - this._buildItem(); - }, - - // Factory for creating an item from a given javascript object - create: function(itemData) { - var item = document.createElement('a'); - item.className = 'tab-item'; - - // If there is an icon, add the icon element - if(itemData.icon) { - var icon = document.createElement('i'); - icon.className = itemData.icon; - item.appendChild(icon); - } - - // If there is a badge, add the badge element - if(itemData.badge) { - var badge = document.createElement('i'); - badge.className = 'badge'; - badge.innerHTML = itemData.badge; - item.appendChild(badge); - item.className = 'tab-item has-badge'; - } - - item.appendChild(document.createTextNode(itemData.title)); - - return new ionic.views.TabBarItem(item); - }, - - _buildItem: function() { - var _this = this, child, children = Array.prototype.slice.call(this.el.children); - - for(var i = 0, j = children.length; i < j; i++) { - child = children[i]; - - // Test if this is a "i" tag with icon in the class name - // TODO: This heuristic might not be sufficient - if(child.tagName.toLowerCase() == 'i' && /icon/.test(child.className)) { - this.icon = child.className; - } - - // Test if this is a "i" tag with badge in the class name - // TODO: This heuristic might not be sufficient - if(child.tagName.toLowerCase() == 'i' && /badge/.test(child.className)) { - this.badge = child.textContent.trim(); - } - } - - this.title = ''; - for(i = 0, j = this.el.childNodes.length; i < j; i++) { - child = this.el.childNodes[i]; - - if (child.nodeName === "#text") { - this.title += child.nodeValue.trim(); - } - } - - this._tapHandler = function(e) { - _this.onTap && _this.onTap(e); - }; - - ionic.on('tap', this._tapHandler, this.el); - }, - onTap: function(e) { - }, - - // Remove the event listeners from this object - destroy: function() { - ionic.off('tap', this._tapHandler, this.el); - }, - - getIcon: function() { - return this.icon; - }, - - getTitle: function() { - return this.title; - }, - - getBadge: function() { - return this.badge; - }, - - setSelected: function(isSelected) { - this.isSelected = isSelected; - if(isSelected) { - this.el.classList.add('active'); - } else { - this.el.classList.remove('active'); - } - } -}); - -ionic.views.TabBar = ionic.views.View.inherit({ - initialize: function(opts) { - this.el = opts.el; - - this.items = []; - - this._buildItems(); - }, - // get all the items for the TabBar - getItems: function() { - return this.items; - }, - - // Add an item to the tab bar - addItem: function(item) { - // Create a new TabItem - var tabItem = ionic.views.TabBarItem.prototype.create(item); - - this.appendItemElement(tabItem); - - this.items.push(tabItem); - this._bindEventsOnItem(tabItem); - }, - - appendItemElement: function(item) { - if(!this.el) { - return; - } - this.el.appendChild(item.el); - }, - - // Remove an item from the tab bar - removeItem: function(index) { - var item = this.items[index]; - if(!item) { - return; - } - item.onTap = undefined; - item.destroy(); - }, - - _bindEventsOnItem: function(item) { - var _this = this; - - if(!this._itemTapHandler) { - this._itemTapHandler = function(e) { - //_this.selectItem(this); - _this.trySelectItem(this); - }; - } - item.onTap = this._itemTapHandler; - }, - - // Get the currently selected item - getSelectedItem: function() { - return this.selectedItem; - }, - - // Set the currently selected item by index - setSelectedItem: function(index) { - this.selectedItem = this.items[index]; - - // Deselect all - for(var i = 0, j = this.items.length; i < j; i += 1) { - this.items[i].setSelected(false); - } - - // Select the new item - if(this.selectedItem) { - this.selectedItem.setSelected(true); - //this.onTabSelected && this.onTabSelected(this.selectedItem, index); - } - }, - - // Select the given item assuming we can find it in our - // item list. - selectItem: function(item) { - for(var i = 0, j = this.items.length; i < j; i += 1) { - if(this.items[i] == item) { - this.setSelectedItem(i); - return; - } - } - }, - - // Try to select a given item. This triggers an event such - // that the view controller managing this tab bar can decide - // whether to select the item or cancel it. - trySelectItem: function(item) { - for(var i = 0, j = this.items.length; i < j; i += 1) { - if(this.items[i] == item) { - this.tryTabSelect && this.tryTabSelect(i); - return; - } - } - }, - - // Build the initial items list from the given DOM node. - _buildItems: function() { - - var item, items = Array.prototype.slice.call(this.el.children); - - for(var i = 0, j = items.length; i < j; i += 1) { - item = new ionic.views.TabBarItem(items[i]); - this.items[i] = item; - this._bindEventsOnItem(item); - } - - if(this.items.length > 0) { - this.selectedItem = this.items[0]; - } - - }, - - // Destroy this tab bar - destroy: function() { - for(var i = 0, j = this.items.length; i < j; i += 1) { - this.items[i].destroy(); - } - this.items.length = 0; - } -}); - -})(window.ionic); diff --git a/test/css/actionsheet.html b/test/css/actionsheet.html new file mode 100644 index 0000000000..d0965deb3f --- /dev/null +++ b/test/css/actionsheet.html @@ -0,0 +1,76 @@ + + + + Action Sheets + + + + + +
+ +
+

Action Sheets

+
+ +
+ +
+ +
+ +
+
+
Do you like ice cream?
+ + +
+
+ +
+
+ +
+
+ + + + + + diff --git a/test/html/bars-clear.html b/test/css/bars-clear.html similarity index 100% rename from test/html/bars-clear.html rename to test/css/bars-clear.html diff --git a/test/html/biglists.html b/test/css/biglists.html similarity index 100% rename from test/html/biglists.html rename to test/css/biglists.html diff --git a/test/html/button-bar.html b/test/css/button-bar.html similarity index 100% rename from test/html/button-bar.html rename to test/css/button-bar.html diff --git a/test/html/buttons.html b/test/css/buttons.html similarity index 100% rename from test/html/buttons.html rename to test/css/buttons.html diff --git a/test/html/cards.html b/test/css/cards.html similarity index 100% rename from test/html/cards.html rename to test/css/cards.html diff --git a/test/html/colors.html b/test/css/colors.html similarity index 100% rename from test/html/colors.html rename to test/css/colors.html diff --git a/test/html/footers.html b/test/css/footers.html similarity index 100% rename from test/html/footers.html rename to test/css/footers.html diff --git a/test/html/grid.html b/test/css/grid.html similarity index 100% rename from test/html/grid.html rename to test/css/grid.html diff --git a/test/html/headers.html b/test/css/headers.html similarity index 100% rename from test/html/headers.html rename to test/css/headers.html diff --git a/test/html/input-checkbox.html b/test/css/input-checkbox.html similarity index 100% rename from test/html/input-checkbox.html rename to test/css/input-checkbox.html diff --git a/test/html/input-radio.html b/test/css/input-radio.html similarity index 100% rename from test/html/input-radio.html rename to test/css/input-radio.html diff --git a/test/html/input-range.html b/test/css/input-range.html similarity index 100% rename from test/html/input-range.html rename to test/css/input-range.html diff --git a/test/html/input-select.html b/test/css/input-select.html similarity index 100% rename from test/html/input-select.html rename to test/css/input-select.html diff --git a/test/html/input-text.html b/test/css/input-text.html similarity index 100% rename from test/html/input-text.html rename to test/css/input-text.html diff --git a/test/html/input-textarea.html b/test/css/input-textarea.html similarity index 100% rename from test/html/input-textarea.html rename to test/css/input-textarea.html diff --git a/test/html/input-toggle.html b/test/css/input-toggle.html similarity index 100% rename from test/html/input-toggle.html rename to test/css/input-toggle.html diff --git a/test/html/lists.html b/test/css/lists.html similarity index 100% rename from test/html/lists.html rename to test/css/lists.html diff --git a/test/css/loading.html b/test/css/loading.html new file mode 100644 index 0000000000..2b24d8dd93 --- /dev/null +++ b/test/css/loading.html @@ -0,0 +1,24 @@ + + + + Loading + + + + +
+

Loading

+
+ + + + + + diff --git a/test/html/modals.html b/test/css/modals.html similarity index 100% rename from test/html/modals.html rename to test/css/modals.html diff --git a/test/html/progress.html b/test/css/progress.html similarity index 100% rename from test/html/progress.html rename to test/css/progress.html diff --git a/test/css/scroll.html b/test/css/scroll.html new file mode 100644 index 0000000000..d89cbdd5ba --- /dev/null +++ b/test/css/scroll.html @@ -0,0 +1,49 @@ + + + + Scroll + + + + + +
+
+ Edit +

Scroll Me

+ Delete +
+
+ +
+ +
+
    +
+
+
+ + + + diff --git a/test/html/search-ios7.html b/test/css/search-ios7.html similarity index 100% rename from test/html/search-ios7.html rename to test/css/search-ios7.html diff --git a/test/html/search.html b/test/css/search.html similarity index 100% rename from test/html/search.html rename to test/css/search.html diff --git a/test/html/side-menus.html b/test/css/side-menus.html similarity index 100% rename from test/html/side-menus.html rename to test/css/side-menus.html diff --git a/test/html/splitPane.html b/test/css/splitPane.html similarity index 100% rename from test/html/splitPane.html rename to test/css/splitPane.html diff --git a/test/html/status-bar.html b/test/css/status-bar.html similarity index 100% rename from test/html/status-bar.html rename to test/css/status-bar.html diff --git a/test/html/tab-bars-icons-bottom.html b/test/css/tab-bars-icons-bottom.html similarity index 100% rename from test/html/tab-bars-icons-bottom.html rename to test/css/tab-bars-icons-bottom.html diff --git a/test/html/tab-bars-icons-left.html b/test/css/tab-bars-icons-left.html similarity index 100% rename from test/html/tab-bars-icons-left.html rename to test/css/tab-bars-icons-left.html diff --git a/test/html/tab-bars-icons-right.html b/test/css/tab-bars-icons-right.html similarity index 100% rename from test/html/tab-bars-icons-right.html rename to test/css/tab-bars-icons-right.html diff --git a/test/html/tab-bars-no-icons.html b/test/css/tab-bars-no-icons.html similarity index 100% rename from test/html/tab-bars-no-icons.html rename to test/css/tab-bars-no-icons.html diff --git a/test/html/tab-bars-only-icons.html b/test/css/tab-bars-only-icons.html similarity index 100% rename from test/html/tab-bars-only-icons.html rename to test/css/tab-bars-only-icons.html diff --git a/test/html/tab-bars.html b/test/css/tab-bars.html similarity index 100% rename from test/html/tab-bars.html rename to test/css/tab-bars.html diff --git a/test/html/tab-with-footer.html b/test/css/tab-with-footer.html similarity index 100% rename from test/html/tab-with-footer.html rename to test/css/tab-with-footer.html diff --git a/js/ext/angular/test/tree_bark.png b/test/css/tree_bark.png similarity index 100% rename from js/ext/angular/test/tree_bark.png rename to test/css/tree_bark.png diff --git a/test/html/type.html b/test/css/type.html similarity index 100% rename from test/html/type.html rename to test/css/type.html diff --git a/test/html/actionsheet.html b/test/html/actionsheet.html index d0965deb3f..2ff5d42bf0 100644 --- a/test/html/actionsheet.html +++ b/test/html/actionsheet.html @@ -1,76 +1,161 @@ - + - Action Sheets - - + Action Sheet + + + + + + - - -
- -
-

Action Sheets

-
- -
-
- Open Sheet -

Homepage

+ + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
- -
- -
-
-
Do you like ice cream?
- -
-
- +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
- +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
- + + + - diff --git a/js/ext/angular/test/anchorScroll.html b/test/html/anchorScroll.html similarity index 100% rename from js/ext/angular/test/anchorScroll.html rename to test/html/anchorScroll.html diff --git a/js/ext/angular/test/app_icon.png b/test/html/app_icon.png similarity index 100% rename from js/ext/angular/test/app_icon.png rename to test/html/app_icon.png diff --git a/js/ext/angular/test/carousel.html b/test/html/carousel.html similarity index 100% rename from js/ext/angular/test/carousel.html rename to test/html/carousel.html diff --git a/js/ext/angular/test/clickTests.html b/test/html/clickTests.html similarity index 100% rename from js/ext/angular/test/clickTests.html rename to test/html/clickTests.html diff --git a/js/ext/angular/test/content.html b/test/html/content.html similarity index 100% rename from js/ext/angular/test/content.html rename to test/html/content.html diff --git a/js/ext/angular/test/contentClick.html b/test/html/contentClick.html similarity index 100% rename from js/ext/angular/test/contentClick.html rename to test/html/contentClick.html diff --git a/js/ext/angular/test/content_defer.html b/test/html/content_defer.html similarity index 100% rename from js/ext/angular/test/content_defer.html rename to test/html/content_defer.html diff --git a/js/ext/angular/test/content_h.html b/test/html/content_h.html similarity index 100% rename from js/ext/angular/test/content_h.html rename to test/html/content_h.html diff --git a/test/html/controllers/nav.html b/test/html/controllers/nav.html deleted file mode 100644 index 87173f986f..0000000000 --- a/test/html/controllers/nav.html +++ /dev/null @@ -1,95 +0,0 @@ - - - - Nav Bars - - - - - - - -
- - - -
-
-
- - - - - - diff --git a/test/html/controllers/route.html b/test/html/controllers/route.html deleted file mode 100644 index e992a22035..0000000000 --- a/test/html/controllers/route.html +++ /dev/null @@ -1,35 +0,0 @@ - - - - Route Controller - - - - - - -
-
-

Routes

-
- -
- Cats -
-
- - - - - - diff --git a/test/html/controllers/sideMenu.html b/test/html/controllers/sideMenu.html deleted file mode 100644 index bbe2390028..0000000000 --- a/test/html/controllers/sideMenu.html +++ /dev/null @@ -1,81 +0,0 @@ - - - - Side Menu - - - - - - - - - - - - - - - diff --git a/test/html/controllers/tabBar.html b/test/html/controllers/tabBar.html deleted file mode 100644 index 8c642a5ede..0000000000 --- a/test/html/controllers/tabBar.html +++ /dev/null @@ -1,108 +0,0 @@ - - - - Tab Bars - - - - - - - -
- -
-

Tab Bars

-
- -
-
-

Tab 1

-

- Friends -

-
-
-

Tab 2

-

- Friends -

-
-
-

Tab 3

-

- Friends -

-
-
-

Tab 4

-

- Friends -

-
-
- -
- - - - - diff --git a/test/html/controllers/tabs.html b/test/html/controllers/tabs.html deleted file mode 100644 index 8ae30d9b75..0000000000 --- a/test/html/controllers/tabs.html +++ /dev/null @@ -1,109 +0,0 @@ - - - - Tab Bars - - - - - - - -
- -
-

Tab Bars

-
- -
- -
-

Tab 1

-

- One -

-
-
-

Tab 2

-

- Two -

-
-
-

Tab 3

-

- Three -

-
-
-

Tab 4

-

- Four -

-
-
-
-
- - - - - diff --git a/js/ext/angular/test/dom-trace.js b/test/html/dom-trace.js similarity index 100% rename from js/ext/angular/test/dom-trace.js rename to test/html/dom-trace.js diff --git a/js/ext/angular/test/embeddedObject.html b/test/html/embeddedObject.html similarity index 100% rename from js/ext/angular/test/embeddedObject.html rename to test/html/embeddedObject.html diff --git a/js/ext/angular/test/gesture.html b/test/html/gesture.html similarity index 100% rename from js/ext/angular/test/gesture.html rename to test/html/gesture.html diff --git a/js/ext/angular/test/has-anything-dynamic.html b/test/html/has-anything-dynamic.html similarity index 100% rename from js/ext/angular/test/has-anything-dynamic.html rename to test/html/has-anything-dynamic.html diff --git a/js/ext/angular/test/header.html b/test/html/header.html similarity index 100% rename from js/ext/angular/test/header.html rename to test/html/header.html diff --git a/js/ext/angular/test/history.html b/test/html/history.html similarity index 100% rename from js/ext/angular/test/history.html rename to test/html/history.html diff --git a/js/ext/angular/test/input.html b/test/html/input.html similarity index 100% rename from js/ext/angular/test/input.html rename to test/html/input.html diff --git a/js/ext/angular/test/list-fit.html b/test/html/list-fit.html similarity index 100% rename from js/ext/angular/test/list-fit.html rename to test/html/list-fit.html diff --git a/js/ext/angular/test/list.html b/test/html/list.html similarity index 100% rename from js/ext/angular/test/list.html rename to test/html/list.html diff --git a/test/html/loading.html b/test/html/loading.html index 2b24d8dd93..8b10017ea5 100644 --- a/test/html/loading.html +++ b/test/html/loading.html @@ -1,24 +1,29 @@ - + Loading - - - - -
-

Loading

-
- - + + + + + + + + + + diff --git a/js/ext/angular/test/map.html b/test/html/map.html similarity index 100% rename from js/ext/angular/test/map.html rename to test/html/map.html diff --git a/js/ext/angular/test/modal.html b/test/html/modal.html similarity index 100% rename from js/ext/angular/test/modal.html rename to test/html/modal.html diff --git a/js/ext/angular/test/nestedScroll.html b/test/html/nestedScroll.html similarity index 100% rename from js/ext/angular/test/nestedScroll.html rename to test/html/nestedScroll.html diff --git a/js/ext/angular/test/overflow.html b/test/html/overflow.html similarity index 100% rename from js/ext/angular/test/overflow.html rename to test/html/overflow.html diff --git a/js/ext/angular/test/poly.html b/test/html/poly.html similarity index 100% rename from js/ext/angular/test/poly.html rename to test/html/poly.html diff --git a/js/ext/angular/test/popup.html b/test/html/popup.html similarity index 100% rename from js/ext/angular/test/popup.html rename to test/html/popup.html diff --git a/js/ext/angular/test/rememberScroll.html b/test/html/rememberScroll.html similarity index 100% rename from js/ext/angular/test/rememberScroll.html rename to test/html/rememberScroll.html diff --git a/test/html/scroll.html b/test/html/scroll.html index d89cbdd5ba..6842edd8f3 100644 --- a/test/html/scroll.html +++ b/test/html/scroll.html @@ -1,49 +1,134 @@ - + - Scroll - - + Content + + + + + + - -
-
- Edit -

Scroll Me

- Delete -
-
- -
- -
-
    -
-
-
- + + + + +

Hourly Forecast

+ +
+
+
+ + +
+ +
+ {{hour.temp}} °F +
+
+
+
+ + Scroll to 100 + + +
+
+
+
+ + diff --git a/js/ext/angular/test/scroll2.html b/test/html/scroll2.html similarity index 100% rename from js/ext/angular/test/scroll2.html rename to test/html/scroll2.html diff --git a/js/ext/angular/test/sideMenu.html b/test/html/sideMenu.html similarity index 100% rename from js/ext/angular/test/sideMenu.html rename to test/html/sideMenu.html diff --git a/js/ext/angular/test/sideMenu2.html b/test/html/sideMenu2.html similarity index 100% rename from js/ext/angular/test/sideMenu2.html rename to test/html/sideMenu2.html diff --git a/js/ext/angular/test/slideBox.html b/test/html/slideBox.html similarity index 100% rename from js/ext/angular/test/slideBox.html rename to test/html/slideBox.html diff --git a/js/ext/angular/test/slideBoxDynamic.html b/test/html/slideBoxDynamic.html similarity index 100% rename from js/ext/angular/test/slideBoxDynamic.html rename to test/html/slideBoxDynamic.html diff --git a/js/ext/angular/test/subControllers.html b/test/html/subControllers.html similarity index 100% rename from js/ext/angular/test/subControllers.html rename to test/html/subControllers.html diff --git a/js/ext/angular/test/tabs-repeat.html b/test/html/tabs-repeat.html similarity index 100% rename from js/ext/angular/test/tabs-repeat.html rename to test/html/tabs-repeat.html diff --git a/js/ext/angular/test/tabs.html b/test/html/tabs.html similarity index 100% rename from js/ext/angular/test/tabs.html rename to test/html/tabs.html diff --git a/js/ext/angular/test/tapInputs.html b/test/html/tapInputs.html similarity index 100% rename from js/ext/angular/test/tapInputs.html rename to test/html/tapInputs.html diff --git a/js/ext/angular/test/toggle.html b/test/html/toggle.html similarity index 100% rename from js/ext/angular/test/toggle.html rename to test/html/toggle.html diff --git a/js/ext/angular/test/viewState.html b/test/html/viewState.html similarity index 100% rename from js/ext/angular/test/viewState.html rename to test/html/viewState.html diff --git a/js/ext/angular/test/controller/ionicScrollController.unit.js b/test/unit/angular/controller/scrollController.unit.js similarity index 100% rename from js/ext/angular/test/controller/ionicScrollController.unit.js rename to test/unit/angular/controller/scrollController.unit.js diff --git a/js/ext/angular/test/directive/ionicBackdrop.unit.js b/test/unit/angular/directive/backdrop.unit.js similarity index 100% rename from js/ext/angular/test/directive/ionicBackdrop.unit.js rename to test/unit/angular/directive/backdrop.unit.js diff --git a/js/ext/angular/test/directive/ionicCheckbox.unit.js b/test/unit/angular/directive/checkbox.unit.js similarity index 96% rename from js/ext/angular/test/directive/ionicCheckbox.unit.js rename to test/unit/angular/directive/checkbox.unit.js index d3dc859476..5357faf17f 100644 --- a/js/ext/angular/test/directive/ionicCheckbox.unit.js +++ b/test/unit/angular/directive/checkbox.unit.js @@ -1,7 +1,7 @@ describe('Ionic Checkbox', function() { var el, scope, compile; - beforeEach(module('ionic.ui.checkbox')); + beforeEach(module('ionic')); beforeEach(inject(function($compile, $rootScope) { compile = $compile; diff --git a/js/ext/angular/test/directive/ionicContent.unit.js b/test/unit/angular/directive/content.unit.js similarity index 99% rename from js/ext/angular/test/directive/ionicContent.unit.js rename to test/unit/angular/directive/content.unit.js index a86bd868f5..0d7b4bd202 100644 --- a/js/ext/angular/test/directive/ionicContent.unit.js +++ b/test/unit/angular/directive/content.unit.js @@ -1,5 +1,5 @@ describe('Ionic Content directive', function() { - var compile, scope; + var compile, scope, timeout, window; beforeEach(module('ionic')); diff --git a/js/ext/angular/test/directive/ionicBar.unit.js b/test/unit/angular/directive/headerFooterBar.unit.js similarity index 100% rename from js/ext/angular/test/directive/ionicBar.unit.js rename to test/unit/angular/directive/headerFooterBar.unit.js diff --git a/js/ext/angular/test/directive/ionicInfiniteScroll.unit.js b/test/unit/angular/directive/infiniteScroll.unit.js similarity index 100% rename from js/ext/angular/test/directive/ionicInfiniteScroll.unit.js rename to test/unit/angular/directive/infiniteScroll.unit.js diff --git a/js/ext/angular/test/directive/ionicList.unit.js b/test/unit/angular/directive/list.unit.js similarity index 99% rename from js/ext/angular/test/directive/ionicList.unit.js rename to test/unit/angular/directive/list.unit.js index 54c4afce68..94fde82e7b 100644 --- a/js/ext/angular/test/directive/ionicList.unit.js +++ b/test/unit/angular/directive/list.unit.js @@ -1,3 +1,5 @@ +describe('',function(){ + describe('$ionicList controller', function() { beforeEach(module('ionic')); function setup(attrs) { @@ -297,3 +299,5 @@ describe('ionOptionButton directive', function() { expect(optionContainer.children().hasClass('button')).toBe(true); })); }); + +}); diff --git a/js/ext/angular/test/directive/ionicNavBackButton.unit.js b/test/unit/angular/directive/navBackButton.unit.js similarity index 100% rename from js/ext/angular/test/directive/ionicNavBackButton.unit.js rename to test/unit/angular/directive/navBackButton.unit.js diff --git a/js/ext/angular/test/directive/ionicNavBar.unit.js b/test/unit/angular/directive/navBar.unit.js similarity index 98% rename from js/ext/angular/test/directive/ionicNavBar.unit.js rename to test/unit/angular/directive/navBar.unit.js index 42dea178d7..9b9a17dd12 100644 --- a/js/ext/angular/test/directive/ionicNavBar.unit.js +++ b/test/unit/angular/directive/navBar.unit.js @@ -2,7 +2,7 @@ describe('ionNavBar', function() { describe('$ionicNavBar controller', function() { var backView = { go: jasmine.createSpy('backViewGo') }; - beforeEach(module('ionic.ui.navBar', function($provide) { + beforeEach(module('ionic', function($provide) { $provide.value('$ionicViewService', { getBackView: jasmine.createSpy('getBackView').andCallFake(function() { return backView; @@ -224,7 +224,7 @@ describe('ionNavBar', function() { }); describe('directive', function() { - beforeEach(module('ionic.ui.navBar')); + beforeEach(module('ionic')); function setup(attrs, content) { var el; inject(function($compile, $rootScope) { diff --git a/js/ext/angular/test/directive/ionicNavClear.unit.js b/test/unit/angular/directive/navClear.unit.js similarity index 100% rename from js/ext/angular/test/directive/ionicNavClear.unit.js rename to test/unit/angular/directive/navClear.unit.js diff --git a/js/ext/angular/test/directive/ionicNavView.unit.js b/test/unit/angular/directive/navView.unit.js similarity index 91% rename from js/ext/angular/test/directive/ionicNavView.unit.js rename to test/unit/angular/directive/navView.unit.js index e09162cff8..ae1ed4b8f6 100644 --- a/js/ext/angular/test/directive/ionicNavView.unit.js +++ b/test/unit/angular/directive/navView.unit.js @@ -1,5 +1,5 @@ describe('Ionic nav-view', function() { - beforeEach(module('ionic.ui.viewState')); + beforeEach(module('ionic')); var compile, scope; beforeEach(inject(function($compile, $rootScope) { diff --git a/js/ext/angular/test/directive/ionicRefresher.unit.js b/test/unit/angular/directive/refresher.unit.js similarity index 100% rename from js/ext/angular/test/directive/ionicRefresher.unit.js rename to test/unit/angular/directive/refresher.unit.js diff --git a/js/ext/angular/test/directive/ionicScroll.unit.js b/test/unit/angular/directive/scroll.unit.js similarity index 100% rename from js/ext/angular/test/directive/ionicScroll.unit.js rename to test/unit/angular/directive/scroll.unit.js diff --git a/js/ext/angular/test/directive/ionicSideMenu.unit.js b/test/unit/angular/directive/sideMenu.unit.js similarity index 98% rename from js/ext/angular/test/directive/ionicSideMenu.unit.js rename to test/unit/angular/directive/sideMenu.unit.js index 9c7344c7b9..8d8fe69d07 100644 --- a/js/ext/angular/test/directive/ionicSideMenu.unit.js +++ b/test/unit/angular/directive/sideMenu.unit.js @@ -113,7 +113,7 @@ describe('Ionic Angular Side Menu', function() { describe('Ionic Side Menu Content Directive', function () { var $compile, element, scope, sideMenusCtrl; - beforeEach(module('ionic.ui.sideMenu')); + beforeEach(module('ionic')); beforeEach(inject(function (_$compile_, _$rootScope_) { $compile = _$compile_; @@ -134,7 +134,7 @@ describe('Ionic Side Menu Content Directive', function () { describe('Ionic Side Menu Directive', function () { var element, scope, sideMenuCtrl; - beforeEach(module('ionic.ui.sideMenu')); + beforeEach(module('ionic')); beforeEach(inject(function (_$compile_, _$rootScope_) { var $compile = _$compile_; diff --git a/js/ext/angular/test/directive/ionicSlideBox.unit.js b/test/unit/angular/directive/slideBox.unit.js similarity index 100% rename from js/ext/angular/test/directive/ionicSlideBox.unit.js rename to test/unit/angular/directive/slideBox.unit.js diff --git a/js/ext/angular/test/directive/ionicTabBar.unit.js b/test/unit/angular/directive/tabs.unit.js similarity index 98% rename from js/ext/angular/test/directive/ionicTabBar.unit.js rename to test/unit/angular/directive/tabs.unit.js index 22bf532203..6d43baecd0 100644 --- a/js/ext/angular/test/directive/ionicTabBar.unit.js +++ b/test/unit/angular/directive/tabs.unit.js @@ -6,17 +6,18 @@ describe('tabs', function() { disableRegisterByTagName: jasmine.createSpy('disableRegisterByTagName') }); })); - it('should register tabs', inject(function($ionicViewService) { + it('should register tabs', inject(function($ionicViewService, $compile, $rootScope) { + $compile('')($rootScope.$new()); expect($ionicViewService.disableRegisterByTagName).toHaveBeenCalledWith('ion-tabs'); })); }); - describe('ionicTabs controller', function() { + describe('$ionicTabs controller', function() { beforeEach(module('ionic')); var ctrl, scope; beforeEach(inject(function($rootScope, $controller) { scope = $rootScope.$new(); - ctrl = $controller('ionicTabs', { + ctrl = $controller('$ionicTabs', { $scope: scope, $element: angular.element('
') }); @@ -266,7 +267,7 @@ describe('tabs', function() { function setup(attrs) { var ctrl; inject(function($controller, $rootScope) { - ctrl = $controller('ionicTab', { + ctrl = $controller('$ionicTab', { $scope: $rootScope.$new(), $attrs: attrs || {} }); @@ -340,7 +341,7 @@ describe('tabs', function() { describe('ionTab directive', function() { var tabDoesMatch; beforeEach(module('ionic', function($controllerProvider) { - $controllerProvider.register('ionicTab', function($scope) { + $controllerProvider.register('$ionicTab', function($scope) { this.$scope = $scope; this.tabMatchesState = jasmine.createSpy('tabMatchesState') .andCallFake(function() { diff --git a/js/ext/angular/test/directive/ionicToggle.unit.js b/test/unit/angular/directive/toggle.unit.js similarity index 100% rename from js/ext/angular/test/directive/ionicToggle.unit.js rename to test/unit/angular/directive/toggle.unit.js diff --git a/js/ext/angular/test/directive/ionicView.unit.js b/test/unit/angular/directive/view.unit.js similarity index 98% rename from js/ext/angular/test/directive/ionicView.unit.js rename to test/unit/angular/directive/view.unit.js index deb34fd8d5..69acf38d8a 100644 --- a/js/ext/angular/test/directive/ionicView.unit.js +++ b/test/unit/angular/directive/view.unit.js @@ -1,5 +1,5 @@ describe('ionView directive', function() { - beforeEach(module('ionic.ui.viewState')); + beforeEach(module('ionic')); function setup(attrs, scopeProps, content) { var el; diff --git a/js/ext/angular/test/service/ionicActionSheet.unit.js b/test/unit/angular/service/actionSheet.unit.js similarity index 93% rename from js/ext/angular/test/service/ionicActionSheet.unit.js rename to test/unit/angular/service/actionSheet.unit.js index 2e17f1ef10..e315c258bc 100644 --- a/js/ext/angular/test/service/ionicActionSheet.unit.js +++ b/test/unit/angular/service/actionSheet.unit.js @@ -1,8 +1,7 @@ describe('Ionic ActionSheet Service', function() { var sheet, timeout, ionicPlatform; - beforeEach(module('ionic.service.actionSheet')); - beforeEach(module('ionic.service.platform')); + beforeEach(module('ionic')); beforeEach(inject(function($ionicActionSheet, $timeout, $ionicPlatform) { sheet = $ionicActionSheet; diff --git a/js/ext/angular/test/service/ionicActivator.unit.js b/test/unit/angular/service/activator.unit.js similarity index 100% rename from js/ext/angular/test/service/ionicActivator.unit.js rename to test/unit/angular/service/activator.unit.js diff --git a/js/ext/angular/test/service/angularOverrides.unit.js b/test/unit/angular/service/angularOverrides.unit.js similarity index 100% rename from js/ext/angular/test/service/angularOverrides.unit.js rename to test/unit/angular/service/angularOverrides.unit.js diff --git a/js/ext/angular/test/service/ionicBind.unit.js b/test/unit/angular/service/bind.unit.js similarity index 98% rename from js/ext/angular/test/service/ionicBind.unit.js rename to test/unit/angular/service/bind.unit.js index 32523305f2..3062d0ea76 100644 --- a/js/ext/angular/test/service/ionicBind.unit.js +++ b/test/unit/angular/service/bind.unit.js @@ -1,5 +1,5 @@ describe('$ionicBind', function() { - beforeEach(module('ionic.service.bind')); + beforeEach(module('ionic')); var $bind, scope, attr, $observeFn; beforeEach(inject(function($ionicBind, $rootScope, $interpolate) { diff --git a/js/ext/angular/test/service/decorators/location.unit.js b/test/unit/angular/service/decorators/location.unit.js similarity index 91% rename from js/ext/angular/test/service/decorators/location.unit.js rename to test/unit/angular/service/decorators/location.unit.js index e189a4c97d..57205c269d 100644 --- a/js/ext/angular/test/service/decorators/location.unit.js +++ b/test/unit/angular/service/decorators/location.unit.js @@ -1,6 +1,6 @@ describe('$location decorator', function() { - beforeEach(module('ionic.decorator.location')); + beforeEach(module('ionic')); describe('.hash()', function() { diff --git a/js/ext/angular/test/service/delegateService.unit.js b/test/unit/angular/service/delegateService.unit.js similarity index 100% rename from js/ext/angular/test/service/delegateService.unit.js rename to test/unit/angular/service/delegateService.unit.js diff --git a/js/ext/angular/test/service/ionicGesture.unit.js b/test/unit/angular/service/gesture.unit.js similarity index 96% rename from js/ext/angular/test/service/ionicGesture.unit.js rename to test/unit/angular/service/gesture.unit.js index 74a69c9bd3..21fe41eb6a 100644 --- a/js/ext/angular/test/service/ionicGesture.unit.js +++ b/test/unit/angular/service/gesture.unit.js @@ -1,7 +1,7 @@ describe('Ionic Gesture Service', function() { var gesture; - beforeEach(module('ionic.service.gesture')); + beforeEach(module('ionic')); beforeEach(inject(function($ionicGesture) { gesture = $ionicGesture; diff --git a/js/ext/angular/test/service/ionicLoading.unit.js b/test/unit/angular/service/loading.unit.js similarity index 100% rename from js/ext/angular/test/service/ionicLoading.unit.js rename to test/unit/angular/service/loading.unit.js diff --git a/js/ext/angular/test/service/ionicModal.unit.js b/test/unit/angular/service/modal.unit.js similarity index 92% rename from js/ext/angular/test/service/ionicModal.unit.js rename to test/unit/angular/service/modal.unit.js index 356e99dc29..4684610142 100644 --- a/js/ext/angular/test/service/ionicModal.unit.js +++ b/test/unit/angular/service/modal.unit.js @@ -1,8 +1,7 @@ describe('Ionic Modal', function() { var modal, q, timeout, ionicPlatform, rootScope; - beforeEach(module('ionic.service.modal')); - beforeEach(module('ionic.service.platform')); + beforeEach(module('ionic')); beforeEach(inject(function($ionicModal, $q, $templateCache, $timeout, $ionicPlatform, $rootScope) { q = $q; @@ -85,25 +84,25 @@ describe('Ionic Modal', function() { expect(m.scope.$destroy).toHaveBeenCalled(); })); - it('Should close on hardware back button', function() { + it('Should close on hardware back button', inject(function($ionicPlatform) { var template = ''; var modalInstance = modal.fromTemplate(template); + spyOn($ionicPlatform, 'registerBackButtonAction').andCallThrough(); modalInstance.show(); timeout.flush(); - expect(modalInstance.isShown()).toBe(true); - - expect( Object.keys(rootScope.$backButtonActions).length ).toEqual(1); + expect($ionicPlatform.registerBackButtonAction).toHaveBeenCalled(); ionicPlatform.hardwareBackButtonClick(); + expect(modalInstance.isShown()).toBe(false); - }); + })); it('should broadcast "modal.shown" on show with self', function() { var template = ''; var m = modal.fromTemplate(template, {}); - spyOn(m.scope.$parent, '$broadcast'); + spyOn(m.scope.$parent, '$broadcast').andCallThrough(); m.show(); timeout.flush(); expect(m.scope.$parent.$broadcast).toHaveBeenCalledWith('modal.shown', m); @@ -125,12 +124,11 @@ describe('Ionic Modal', function() { //By the time m.remove() is done, our scope will be destroyed. so we have to save the modal //it gives us - spyOn(m.scope.$parent, '$broadcast').andCallFake(function(e, modal) { - broadcastedModal = modal; - }); + spyOn(m.scope.$parent, '$broadcast').andCallThrough(); + spyOn(m.scope, '$destroy'); m.remove(); - expect(m.scope.$parent.$broadcast).toHaveBeenCalledWith('modal.removed'); + expect(m.scope.$parent.$broadcast).toHaveBeenCalledWith('modal.removed', m); timeout.flush(); })); diff --git a/js/ext/angular/test/service/ionicPlatform.unit.js b/test/unit/angular/service/platform.unit.js similarity index 97% rename from js/ext/angular/test/service/ionicPlatform.unit.js rename to test/unit/angular/service/platform.unit.js index 351e2c4b22..407cc69f2a 100644 --- a/js/ext/angular/test/service/ionicPlatform.unit.js +++ b/test/unit/angular/service/platform.unit.js @@ -1,13 +1,14 @@ describe('Ionic Platform Service', function() { var window, ionicPlatform, rootScope; - beforeEach(module('ionic.service.platform')); + beforeEach(module('ionic')); beforeEach(inject(function($window, $ionicPlatform, $rootScope) { window = $window; ionic.Platform.ua = ''; ionicPlatform = $ionicPlatform; rootScope = $rootScope; + $ionicPlatform.$backButtonActions = {}; })); it('should set platform name', function() { @@ -275,9 +276,9 @@ describe('Ionic Platform Service', function() { it('should register/deregister a hardware back button action and add it to $ionicPlatform.backButtonActions', function() { var deregisterFn = ionicPlatform.registerBackButtonAction(function(){}); - expect( Object.keys( rootScope.$backButtonActions ).length ).toEqual(1); + expect( Object.keys( ionicPlatform.$backButtonActions ).length ).toEqual(1); deregisterFn(); - expect( Object.keys( rootScope.$backButtonActions ).length ).toEqual(0); + expect( Object.keys( ionicPlatform.$backButtonActions ).length ).toEqual(0); }); it('should register multiple back button actions and only call the highest priority on hardwareBackButtonClick', function() { diff --git a/js/ext/angular/test/service/ionicPopup.unit.js b/test/unit/angular/service/popup.unit.js similarity index 100% rename from js/ext/angular/test/service/ionicPopup.unit.js rename to test/unit/angular/service/popup.unit.js diff --git a/js/ext/angular/test/service/ionicTap.unit.js b/test/unit/angular/service/tap.unit.js similarity index 100% rename from js/ext/angular/test/service/ionicTap.unit.js rename to test/unit/angular/service/tap.unit.js diff --git a/js/ext/angular/test/service/ionicTemplateLoader.unit.js b/test/unit/angular/service/templateLoader.unit.js similarity index 100% rename from js/ext/angular/test/service/ionicTemplateLoader.unit.js rename to test/unit/angular/service/templateLoader.unit.js diff --git a/js/ext/angular/test/service/ionicViewService.unit.js b/test/unit/angular/service/viewService.unit.js similarity index 99% rename from js/ext/angular/test/service/ionicViewService.unit.js rename to test/unit/angular/service/viewService.unit.js index 260b3a7c54..4d001b0655 100644 --- a/js/ext/angular/test/service/ionicViewService.unit.js +++ b/test/unit/angular/service/viewService.unit.js @@ -1,10 +1,7 @@ describe('Ionic View Service', function() { var viewService, rootScope, stateProvider, window; - beforeEach(module('ionic.service.view')); - beforeEach(module('ui.router')); - - beforeEach(module(function ($stateProvider, $provide) { + beforeEach(module('ionic', function ($stateProvider, $provide) { stateProvider = $stateProvider; $stateProvider diff --git a/test/unit/controllers/navController.unit.js b/test/unit/controllers/navController.unit.js deleted file mode 100644 index 42f6b72e35..0000000000 --- a/test/unit/controllers/navController.unit.js +++ /dev/null @@ -1,60 +0,0 @@ -describe('NavController', function() { - var ctrl, navBarEl, contentEl; - - var content = function(title) { - return { - el: document.createElement('div'), - title: title, - detach: function() { - this.el.parentNode && this.el.parentNode.removeChild(this.el); - }, - attach: function() { - } - }; - }; - - beforeEach(function() { - navBarEl = document.createElement('div'); - contentEl = document.createElement('div'); - - ctrl = new ionic.controllers.NavController({ - navBar: new ionic.views.NavBar({el: navBarEl }), - content: { el: contentEl } - }); - }); - - it('Should load controllers', function() { - ctrl = new ionic.controllers.NavController({ - navBar: new ionic.views.NavBar({el: navBarEl }), - content: { el: contentEl }, - controllers: [{}] - }); - expect(ctrl.getControllers().length).toEqual(1); - }); - - it('Should push controller', function() { - ctrl.push(content('Page 1')); - expect(ctrl.getControllers().length).toEqual(1); - ctrl.push(content('Page 2')); - expect(ctrl.getControllers().length).toEqual(2); - var last = ctrl.pop(); - expect(ctrl.getControllers().length).toEqual(1); - expect(last.title).toEqual('Page 2'); - }); - - it('Should change top view controller', function() { - expect(ctrl.getTopController()).toBe(undefined); - var c1 = content('Page 1'); - var c2 = content('Page 2'); - ctrl.push(c1); - expect(ctrl.getTopController()).toEqual(c1); - ctrl.push(c2); - expect(ctrl.getTopController()).toEqual(c2); - ctrl.pop(); - expect(ctrl.getTopController()).toEqual(c1); - - // Make sure we can't pop the first one off - ctrl.pop(); - expect(ctrl.getTopController()).toEqual(c1); - }); -}); diff --git a/test/unit/controllers/tabBarController.unit.js b/test/unit/controllers/tabBarController.unit.js deleted file mode 100644 index ae2612bcac..0000000000 --- a/test/unit/controllers/tabBarController.unit.js +++ /dev/null @@ -1,88 +0,0 @@ -describe('TabBarController', function() { - var ctrl; - - beforeEach(function() { - var tabEl = $('
'); - ctrl = new ionic.controllers.TabBarController({ - tabBar: new ionic.views.TabBar({ - el: tabEl.get(0) - }) - }); - }); - - it('Should add Controllers', function() { - ctrl.addController({ - title: 'Item 1', - icon: 'icon-home', - badge: 'Badge 1' - }); - - expect(ctrl.getController(0).title).toEqual('Item 1'); - expect(ctrl.getController(0).badge).toEqual('Badge 1'); - - var items = ctrl.tabBar.getItems(); - expect(items.length).toEqual(1); - - expect(items[0].getTitle()).toEqual('Item 1'); - expect(items[0].getBadge()).toEqual('Badge 1'); - expect(items[0].getIcon()).toEqual('icon-home'); - - }); - - it('Should set Controllers', function() { - var Controllers = [ - { title: 'Item 1' }, - { title: 'Item 2' }, - { title: 'Item 3' }, - ]; - ctrl.setControllers(Controllers); - - expect(ctrl.getControllers()).toBe(Controllers); - }); - - it('Should select Controller', function() { - Controller = { - title: 'Item 1' - }; - - ctrl.addController(Controller); - - ctrl.selectController(0); - - expect(ctrl.getSelectedController()).toEqual(Controller); - }); - - it('Should trigger lifecycle methods', function() { - Controller = { - title: 'Item 1' - }; - - spyOn(ctrl, 'controllerWillChange'); - spyOn(ctrl, 'controllerChanged'); - - ctrl.addController(Controller); - ctrl.selectController(0); - expect(ctrl.controllerWillChange).toHaveBeenCalled(); - expect(ctrl.controllerChanged).toHaveBeenCalled(); - }); - - it('Should allow cancelling Controller switch', function() { - var tabEl = $('
'); - ctrl = new ionic.controllers.TabBarController({ - tabBar: new ionic.views.TabBar({ el: tabEl.get(0) }), - controllerWillChange: function(Controller) { return false; } - }); - - ctrl.addController({ - title: 'Item 1' - }); - ctrl.addController({ - title: 'Item 2' - }); - ctrl.selectController(1); - - // Make sure the Controller didn't switch - expect(ctrl.getSelectedController()).toBe(ctrl.getController(0)); - }); - -}); diff --git a/test/unit/views/tabBar.unit.js b/test/unit/views/tabBar.unit.js deleted file mode 100644 index c715bf7308..0000000000 --- a/test/unit/views/tabBar.unit.js +++ /dev/null @@ -1,147 +0,0 @@ -describe('TabBar view', function() { - var element, tabBar, items; - - beforeEach(function() { - element = $('
' + - ' Tab 1' + - 'Badge 1 Tab 2' + - 'Tab 3'); - - tabBar = new ionic.views.TabBar({ - el: element.get(0) - }); - - items = tabBar.getItems(); - }); - it('Should read tabs', function() { - expect(items.length).toEqual(3); - expect(items[0].getTitle()).toEqual('Tab 1'); - expect(items[1].getTitle()).toEqual('Tab 2'); - expect(items[2].getTitle()).toEqual('Tab 3'); - }); - - it('Should read badge', function() { - expect(items[1].getBadge()).toEqual('Badge 1'); - }); - - it('Should select', function() { - // Track selection object - tabBar.setSelectedItem(1); - expect(tabBar.getSelectedItem().getTitle()).toEqual('Tab 2'); - tabBar.setSelectedItem(0); - expect(tabBar.getSelectedItem().getTitle()).toEqual('Tab 1'); - tabBar.setSelectedItem(2); - expect(tabBar.getSelectedItem().getTitle()).toEqual('Tab 3'); - - // Track class change - expect(tabBar.getSelectedItem().el.classList.contains('active')).toEqual(true); - - // Make sure the other ones have theirs cleared - expect(items[0].el.classList.contains('active')).toEqual(false); - expect(items[1].el.classList.contains('active')).toEqual(false); - expect(items[2].el.classList.contains('active')).toEqual(true); - - tabBar.setSelectedItem(0); - expect(items[0].el.classList.contains('active')).toEqual(true); - expect(items[1].el.classList.contains('active')).toEqual(false); - expect(items[2].el.classList.contains('active')).toEqual(false); - }); - - - it('Should handle item click event', function() { - var item = items[0]; - spyOn(tabBar, 'trySelectItem'); - - var event = document.createEvent('Event'); - event.initEvent('tap', true, true); - event.detail = { - target: item.el - }; - item.el.dispatchEvent(event); - - //expect(item.onTap).toHaveBeenCalled(); - expect(tabBar.trySelectItem).toHaveBeenCalled(); - }); - - - it('Should unbind item on destroy', function() { - var item = items[0]; - spyOn(item, 'onTap'); - - var event = document.createEvent('Event'); - event.initEvent('tap', true, true); - event.detail = { - target: item.el - }; - item.el.dispatchEvent(event); - - expect(item.onTap).toHaveBeenCalled(); - - item.onTap.isSpy = false; - spyOn(item, 'onTap'); - - tabBar.destroy(); - - event = document.createEvent('Event'); - event.initEvent('tap', true, true); - event.detail = { - target: item.el - }; - item.el.dispatchEvent(event); - - expect(item.onTap).not.toHaveBeenCalled(); - }); -}); - -describe('TabBarItem view', function() { - var element, tabBar, items; - - beforeEach(function() { - element = $('
' + - ' Tab 1' + - 'Tab 2' + - 'Tab 3'); - - tabBar = new ionic.views.TabBar({ - el: element.get(0) - }); - - items = tabBar.getItems(); - }); - it('Should set item title', function() { - var item = items[0]; - expect(item.getTitle()).toBe('Tab 1'); - }); - it('Should set item icon', function() { - - var item = items[0]; - expect(item.getIcon()).toBe('icon-home'); - }); - it('Should unbind item on destroy', function() { - var item = items[0]; - spyOn(item, 'onTap'); - - var event = document.createEvent('Event'); - event.initEvent('tap', true, true); - event.detail = { - target: item.el - }; - item.el.dispatchEvent(event); - - expect(item.onTap).toHaveBeenCalled(); - - item.onTap.isSpy = false; - spyOn(item, 'onTap'); - - item.destroy(); - - event = document.createEvent('Event'); - event.initEvent('tap', true, true); - event.detail = { - target: item.el - }; - item.el.dispatchEvent(event); - - expect(item.onTap).not.toHaveBeenCalled(); - }); -});