Compare commits

...

54 Commits

Author SHA1 Message Date
Adam Bradley
bbdfb1d19a v0.9.20, ALPHA LYNX! 2014-01-14 21:53:55 -06:00
Adam Bradley
45ad4acacd fix so content width stays the same during transition 2014-01-14 21:48:27 -06:00
Adam Bradley
cf6598b09f update tab broadcasts, fixes #415 2014-01-14 13:07:52 -06:00
Adam Bradley
9efe95ef06 fix double call on back button 2014-01-14 13:00:37 -06:00
Adam Bradley
64d8fd207a platform detect updates 2014-01-14 00:59:25 -06:00
Adam Bradley
41a7b45f0e remove flicker before back view transition 2014-01-13 22:53:51 -06:00
Max Lynch
27311d5d18 Added support for offset start scroll view 2014-01-13 19:29:32 -06:00
Max Lynch
db6ce5044f Added padding to content example 2014-01-13 17:11:44 -06:00
Adam Bradley
567d6dae3b fix padding in content directive 2014-01-13 16:44:22 -06:00
Max Lynch
7e2b909346 Fixed #409 - null device platform (cordova) 2014-01-13 15:49:08 -06:00
Max Lynch
72c97e8fce Fixed duplicate backbutton hardware event 2014-01-13 15:47:16 -06:00
Max Lynch
fc890ea1c5 Removed unused .content for #355 2014-01-13 12:27:53 -06:00
Adam Bradley
124a6d1616 slim it down 2014-01-13 12:26:33 -06:00
Max Lynch
3fb3fab11c Merge branch 'pr/400' - fixes #397 2014-01-13 12:22:05 -06:00
Adam Bradley
4168b9a6fd update changelog 2014-01-13 12:18:14 -06:00
Max Lynch
e02e1c9c26 Merge branch 'master' of https://github.com/driftyco/ionic
Conflicts:
	dist/js/ionic-angular.min.js
	dist/js/ionic.min.js
2014-01-13 12:10:30 -06:00
Max Lynch
cd13cf396d Added Android back button support to action sheet, modal 2014-01-13 12:03:06 -06:00
Adam Bradley
cafde83d0d dist rebuild 2014-01-13 12:01:36 -06:00
Adam Bradley
7c1fed40ea Merge branch 'master' of https://github.com/driftyco/ionic 2014-01-13 12:00:12 -06:00
Adam Bradley
2b2492d2d4 add padding classname for content directive 2014-01-13 11:59:58 -06:00
Max Lynch
2008a72204 Fixed #242 - modal transition issue on start 2014-01-13 11:42:02 -06:00
Adam Bradley
c35e4641fb Update CONTRIBUTING.md 2014-01-13 10:51:04 -06:00
Max Lynch
86d6889628 Fixed #380 - rename ionic services to use $ionic prefix 2014-01-13 10:46:41 -06:00
Max Lynch
8d59625d4f Rebuild 2014-01-13 10:17:59 -06:00
Max Lynch
5c414bbf00 Merge branch 'master' of https://github.com/driftyco/ionic
Conflicts:
	dist/js/ionic-angular.min.js
2014-01-13 10:17:45 -06:00
Max Lynch
d90ae2c9af Fixed #279 - transclusion issue with content 2014-01-13 10:17:28 -06:00
Adam Bradley
0d592d7063 version number bump to 0.9.20-alpha 2014-01-13 09:46:43 -06:00
Adam Bradley
3a598aa21e switching tabs should not use $animate 2014-01-13 09:37:16 -06:00
Adam Bradley
7581c45b21 update nav-bar test 2014-01-13 09:35:22 -06:00
Adam Bradley
4f155964dd nav bar hidden by default 2014-01-12 23:00:30 -06:00
Adam Bradley
3124ef3981 update how view's set titles, closes #337 2014-01-12 22:39:10 -06:00
Adam Bradley
8982a8ad40 Merge branch 'master' of https://github.com/driftyco/ionic
Conflicts:
	dist/js/ionic-angular.min.js
	dist/js/ionic.min.js
2014-01-12 22:00:48 -06:00
Adam Bradley
d4a9bed1d7 update enteringScope for view transition 2014-01-12 21:56:23 -06:00
Max Lynch
624669a901 Merge pull request #404 from matiboy/403-optional-active-slide-fixing
(fix 403) Make active slide optional
2014-01-12 19:51:20 -08:00
matiboy
c4b66bc3d3 Make active slide optional 2014-01-13 11:12:41 +08:00
Max Lynch
ddadc461c0 Possible solution for #327 - platform detect 2014-01-12 20:46:53 -06:00
Max Lynch
3bb36d3fda Rebuild 2014-01-12 20:25:34 -06:00
Max Lynch
8be060124a Merge branch 'master' of https://github.com/driftyco/ionic
Conflicts:
	dist/js/ionic-angular.min.js
2014-01-12 20:25:23 -06:00
Max Lynch
c5c68c2bf1 Removed ng-class on list item to not clash with user's use of ng-class 2014-01-12 20:24:44 -06:00
Adam Bradley
944e89acba deregister watches on view destroy 2014-01-12 20:12:53 -06:00
Adam Bradley
ff310600d9 fix view hideNavBar attribute, closes #394 2014-01-12 13:41:00 -06:00
Adam Bradley
71e1f98f19 show/hide back button from view 2014-01-11 23:25:13 -06:00
Adam Bradley
f4d980800f removed used file 2014-01-11 22:27:07 -06:00
Adam Bradley
1908a0ffa0 Merge pull request #396 from calendee/listExampleFix
Fixed invalid end tag for nav-view.
2014-01-11 14:41:58 -08:00
Justin Noel
1b2ebaef54 Fixed invalid end tag for nav-view.
Signed-off-by: Justin Noel <github@calendee.com>
2014-01-11 06:45:18 -06:00
Adam Bradley
e9cb20e57a ionicons v1.4.1 2014-01-11 00:52:05 -06:00
Adam Bradley
251025e512 clear view history, closes #393 2014-01-11 00:43:41 -06:00
Adam Bradley
76d185125a button-block fix for input, closes #340 2014-01-11 00:10:49 -06:00
Adam Bradley
1f0a94a26e disable button css, closes #335 2014-01-11 00:01:12 -06:00
Adam Bradley
e390e2e1c3 ios7 search bar, fixes #374 2014-01-10 23:49:19 -06:00
Adam Bradley
032d21bd13 removed ios7 theme 2014-01-10 23:39:04 -06:00
Max Lynch
721048b599 Merge pull request #389 from malixsys/master
ngRoute no longer needed, $route now provided by ui.router
2014-01-10 16:52:07 -08:00
M Alix
108507629d ngRoute no longer needed, $route now provided by ui.router 2014-01-10 18:59:41 -05:00
Max Lynch
28bf244d83 Removed failing nav router test 2014-01-10 16:30:37 -06:00
69 changed files with 1470 additions and 1344 deletions

View File

@@ -1,4 +1,12 @@
## 0.9.20 "Alpha Lynx" (2014-01-14)
- Improved transitions between views
- Fixed hide-nav-bar/hide-back-button view attributes
- Removed title attributes from DOM
- Remove nav title if the entering view doesn't have one
- Fix padding being added to content directive
## 0.9.19 "Alpha Koala" (2014-01-10)
- Created ViewState Service to track navigation history
- Created navView directive

View File

@@ -2,12 +2,16 @@ Please read the contributing guide on the ionic website: http://ionicframework.c
### Creating an Issue
If you think you might have found a bug, please start by making sure it hasn't already been [reported](https://github.com/driftyco/ionic/issues?state=open). You can search through existing issues to see if someone's reported one similar to yours.
If you have a question on how something works you might want to visit the [Ionic Forum](http://forum.ionicframework.com/) first.
If you think you have found a bug, or have a new feature idea, please start by making sure it hasn't already been [reported](https://github.com/driftyco/ionic/issues?state=open). You can search through existing issues to see if someone's reported one similar to yours.
If not, then [create a plunkr](http://plnkr.co/edit/vD0O9M?p=preview) that demonstrates the problem (try to use as little code as possible: the more minimalist, the faster we can debug it).
Next, [create a new issue](https://github.com/driftyco/ionic/issues/new) that briefly explains the problem, and provides a bit of background as to the circumstances that triggered it. Don't forget to include the link to that plunkr you created!
### Pull Request Guidelines
When in doubt, keep your pull requests small. To give a PR the best chance of getting accepted, do not bundle more than one "feature" or bug fix per PR. Doing so makes it very hard to accept it if one of the fixes has issues.

View File

@@ -75,7 +75,6 @@ module.exports = function(grunt) {
dist: {
files: {
'dist/css/ionic.css': 'scss/ionic.scss',
'dist/css/themes/ionic-ios7.css': 'scss/themes/ios7/ionic-ios7.scss'
}
}
},
@@ -83,7 +82,6 @@ module.exports = function(grunt) {
dist: {
files: {
'dist/css/ionic.min.css': 'dist/css/ionic.css',
'dist/css/themes/ionic-ios7.min.css': 'dist/css/themes/ionic-ios7.css'
}
}
},

View File

@@ -1,6 +1,6 @@
{
"name": "ionic",
"version": "0.9.19",
"version": "0.9.20",
"homepage": "https://github.com/driftyco/ionic",
"authors": [
"Max Lynch <max@drifty.com>",

View File

@@ -1,7 +1,7 @@
{
"repo": "driftyco/ionic",
"development": {},
"version": "0.9.19",
"version": "0.9.20",
"styles": [
"dist/css/ionic.css"
],

56
dist/css/ionic.css vendored
View File

@@ -2,7 +2,7 @@
* Copyright 2014 Drifty Co.
* http://drifty.com/
*
* Ionic, v0.9.19
* Ionic, v0.9.20
* A powerful HTML5 mobile app framework.
* http://ionicframework.com/
*
@@ -12,15 +12,15 @@
*
*/
/*!
Ionicons, v1.4.0
Ionicons, v1.4.1
Created by Ben Sperry for the Ionic Framework, http://ionicons.com/
https://twitter.com/helloimben https://twitter.com/ionicframework
MIT License: https://github.com/driftyco/ionicons
*/
@font-face {
font-family: "Ionicons";
src: url("../fonts/ionicons.eot?v=1.4.0");
src: url("../fonts/ionicons.eot?v=1.4.0#iefix") format("embedded-opentype"), url("../fonts/ionicons.ttf?v=1.4.0") format("truetype"), url("../fonts/ionicons.woff?v=1.4.0") format("woff"), url("../fonts/ionicons.svg?v=1.4.0#Ionicons") format("svg");
src: url("../fonts/ionicons.eot?v=1.4.1");
src: url("../fonts/ionicons.eot?v=1.4.1#iefix") format("embedded-opentype"), url("../fonts/ionicons.ttf?v=1.4.1") format("truetype"), url("../fonts/ionicons.woff?v=1.4.1") format("woff"), url("../fonts/ionicons.svg?v=1.4.1#Ionicons") format("svg");
font-weight: normal;
font-style: normal; }
@@ -2551,18 +2551,6 @@ body, .ionic-body {
text-rendering: optimizeLegibility;
-webkit-user-drag: none; }
.content:before,
.content:after {
display: block;
overflow: hidden;
height: 0;
content: "\00a0"; }
.content {
position: absolute;
width: 100%;
height: 100%; }
.scroll-content {
top: 0;
right: 0;
@@ -2606,6 +2594,9 @@ body, .ionic-body {
position: absolute;
z-index: 9999; }
.ng-animate .scroll-bar {
visibility: hidden; }
.scroll-bar-h {
height: 3px;
left: 2px;
@@ -5486,12 +5477,19 @@ input[type="range"] {
button.button-block,
button.button-full,
.button-full > button.button {
.button-full > button.button,
input.button.button-block {
width: 100%; }
a.button {
text-decoration: none; }
.button.disabled,
.button[disabled] {
opacity: .4;
cursor: default !important;
pointer-events: none; }
/**
* Button Bar
* --------------------------------------------------
@@ -5810,8 +5808,9 @@ a.button {
right: -1px;
bottom: 0;
left: -1px;
border-left: 1px solid #ddd;
border-right: 1px solid #ddd; }
width: auto;
border-right: 1px solid #ddd;
border-left: 1px solid #ddd; }
.slide-left-right-ios7 > .ng-enter, .slide-left-right-ios7.ng-enter {
/* NEW content placed far RIGHT BEFORE it slides IN from the RIGHT */
-webkit-transform: translate3d(100%, 0, 0);
@@ -5836,8 +5835,9 @@ a.button {
right: -1px;
bottom: 0;
left: -1px;
border-left: 1px solid #ddd;
border-right: 1px solid #ddd; }
width: auto;
border-right: 1px solid #ddd;
border-left: 1px solid #ddd; }
.slide-left-right-ios7.reverse > .ng-enter, .slide-left-right-ios7.reverse.ng-enter {
/* NEW content placed far LEFT BEFORE it slides IN from the LEFT */
-webkit-transform: translate3d(-100%, 0, 0);
@@ -6055,9 +6055,9 @@ a.button {
animation-name: slideOutToRight; }
.slide-in-up {
-webkit-transform: translate3d(0, 0%, 0);
-moz-transform: translate3d(0, 0%, 0);
transform: translate3d(0, 0%, 0);
-webkit-transform: translate3d(0, 0, 0);
-moz-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
opacity: 1; }
.slide-in-up.ng-enter, .slide-in-up .ng-enter {
-webkit-transform: translate3d(0, 100%, 0);
@@ -6099,9 +6099,9 @@ a.button {
-webkit-animation-timing-function: cubic-bezier(0.1, 0.7, 0.1, 1);
-moz-animation-timing-function: cubic-bezier(0.1, 0.7, 0.1, 1);
animation-timing-function: cubic-bezier(0.1, 0.7, 0.1, 1);
-webkit-animation-fill-mode: both;
-moz-animation-fill-mode: both;
animation-fill-mode: both; }
-webkit-animation-fill-mode: forwards;
-moz-animation-fill-mode: forwards;
animation-fill-mode: forwards; }
.slide-in-up-add-active {
-webkit-animation-name: slideInUp;
@@ -6542,6 +6542,8 @@ a.button {
*/
.platform-ios7 .bar-header {
height: 64px; }
.platform-ios7 .bar-header.item-input-inset .item-input-wrapper {
margin-top: 19px !important; }
.platform-ios7 .bar-header > * {
margin-top: 20px; }
.platform-ios7 .has-header {

View File

File diff suppressed because one or more lines are too long

View File

@@ -1,149 +0,0 @@
/*!
* Copyright 2013 Drifty Co.
* http://drifty.com/
* Ionic - a powerful HTML5 mobile app framework.
* http://ionicframework.com/
*
*
* By @maxlynch, @helloimben, @adamdbradley <3
*
* Licensed under the MIT license. Please see LICENSE for more information.
*
*/
/**
* Nav controllers and header bar animations
*/
/*
.content-slide-in {
&.ng-enter, > .ng-enter {
-webkit-transition: 0.5s ease-in-out all;
-webkit-transform:translate3d(100%,0,0) ;
box-shadow: -1px 0px 10px rgba(0,0,0,0.6);
}
&.ng-enter-active, > .ng-enter-active {
-webkit-transform:translate3d(0,0,0) ;
}
&.ng-leave, > .ng-leave {
-webkit-transition: 0.5s ease-in-out all;
-webkit-transform:translate3d(0%,0,0);
}
&.ng-leave-active, > .ng-leave-active {
-webkit-transform:translate3d(-10%,0,0);
opacity: 0.8;
}
}
*/
.content-slide-out.ng-enter, .content-slide-out > .ng-enter {
z-index: 1;
-webkit-transition: 0.5s ease-in-out all;
-webkit-transform: translate3d(-100%, 0, 0);
box-shadow: -1px 0px 10px rgba(0, 0, 0, 0.6); }
.content-slide-out.ng-enter-active, .content-slide-out > .ng-enter-active {
-webkit-transform: translate3d(0, 0, 0); }
.content-slide-out.ng-leave, .content-slide-out > .ng-leave {
z-index: 0;
-webkit-transition: 0.5s ease-in-out all;
-webkit-transform: translate3d(0%, 0, 0); }
.content-slide-out.ng-leave-active, .content-slide-out > .ng-leave-active {
-webkit-transform: translate3d(10%, 0, 0);
opacity: 0.8; }
.bar-title-in-add {
-webkit-transition: -webkit-transform 0.5s ease-in-out, opacity 0.5s ease-in-out;
-webkit-transform: translate3d(100%, 0, 0);
opacity: 0; }
.bar-title-in-add-active {
-webkit-transform: translate3d(0px, 0, 0);
opacity: 1; }
.bar-title-out-add {
-webkit-transition: -webkit-transform 0.5s ease-in-out, opacity 0.5s ease-in-out; }
.bar-title-out-add-active {
-webkit-transform: translate3d(-100%, 0, 0);
opacity: 0; }
.bar-button-in {
opacity: 0; }
.bar-button-in-add {
-webkit-transition: -webkit-transform 0.5s ease-in-out, opacity 0.5s ease-in-out;
-webkit-transform: translate3d(50%, 0, 0);
opacity: 0; }
.bar-button-in-active {
-webkit-transform: translate3d(0px, 0, 0);
opacity: 1; }
/**
* Tab controller animations
*/
.fade-in-out.ng-enter, .fade-in-out > .ng-enter {
opacity: 0;
-webkit-transition: opacity 0.3s ease-in-out; }
.fade-in-out.ng-enter-active, .fade-in-out > .ng-enter-active {
opacity: 1; }
.fade-in-out.ng-leave, .fade-in-out > .ng-leave {
opacity: 1;
-webkit-transition: opacity 0.3s ease-in-out; }
.fade-in-out.ng-leave-active, .fade-in-out > .ng-leave-active {
opacity: 0; }
/* the overall container of the toggle */
.toggle {
display: inline-block; }
/* hide the actual checkbox */
.toggle input {
display: none; }
.toggle .track {
/* the background of the toggle's track area */
/* also the track appearance when the toggle is "off" */
position: relative;
display: inline-block;
box-sizing: border-box;
width: 54px;
height: 32px;
border: solid 2px #dddddd;
border-radius: 20px;
background-color: white;
cursor: pointer;
transition: 0.4s ease; }
.toggle .handle {
/* the handle (circle) thats inside the toggle's track area */
/* also the appearance when the handle is "off" */
position: absolute;
display: block;
width: auto;
/* override defaults */
height: auto;
/* override defaults */
box-shadow: 0 0 2px rgba(0, 0, 0, 0.5), 0 4px 5px rgba(0, 0, 0, 0.25);
border-radius: 20px;
background-color: white;
left: 0;
top: 0;
bottom: 0;
right: 20px;
transition: 0.2s ease;
transition-property: left, right;
transition-delay: 0s, .05s; }
.toggle :checked + .track {
/* When the toggle is "on" */
/* the track when the toggle is "on" */
border-color: #4bd863;
background-color: #ccc;
box-shadow: inset 0 0 0 20px #4bd863;
transition: 0.2s ease;
/* the handle when the toggle is "on" */ }
.toggle :checked + .track .handle {
background-color: white;
right: 0;
left: 20px;
-webkit-transform: none;
transition-delay: .05s, 0s; }

View File

@@ -1,13 +0,0 @@
/*!
* Copyright 2013 Drifty Co.
* http://drifty.com/
* Ionic - a powerful HTML5 mobile app framework.
* http://ionicframework.com/
*
*
* By @maxlynch, @helloimben, @adamdbradley <3
*
* Licensed under the MIT license. Please see LICENSE for more information.
*
*/.content-slide-out.ng-enter,.content-slide-out>.ng-enter{z-index:1;-webkit-transition:.5s ease-in-out all;-webkit-transform:translate3d(-100%,0,0);box-shadow:-1px 0 10px rgba(0,0,0,.6)}.content-slide-out.ng-enter-active,.content-slide-out>.ng-enter-active{-webkit-transform:translate3d(0,0,0)}.content-slide-out.ng-leave,.content-slide-out>.ng-leave{z-index:0;-webkit-transition:.5s ease-in-out all;-webkit-transform:translate3d(0%,0,0)}.content-slide-out.ng-leave-active,.content-slide-out>.ng-leave-active{-webkit-transform:translate3d(10%,0,0);opacity:.8}.bar-title-in-add{-webkit-transition:-webkit-transform .5s ease-in-out,opacity .5s ease-in-out;-webkit-transform:translate3d(100%,0,0);opacity:0}.bar-title-in-add-active{-webkit-transform:translate3d(0px,0,0);opacity:1}.bar-title-out-add{-webkit-transition:-webkit-transform .5s ease-in-out,opacity .5s ease-in-out}.bar-title-out-add-active{-webkit-transform:translate3d(-100%,0,0);opacity:0}.bar-button-in{opacity:0}.bar-button-in-add{-webkit-transition:-webkit-transform .5s ease-in-out,opacity .5s ease-in-out;-webkit-transform:translate3d(50%,0,0);opacity:0}.bar-button-in-active{-webkit-transform:translate3d(0px,0,0);opacity:1}.fade-in-out.ng-enter,.fade-in-out>.ng-enter{opacity:0;-webkit-transition:opacity .3s ease-in-out}.fade-in-out.ng-enter-active,.fade-in-out>.ng-enter-active{opacity:1}.fade-in-out.ng-leave,.fade-in-out>.ng-leave{opacity:1;-webkit-transition:opacity .3s ease-in-out}.fade-in-out.ng-leave-active,.fade-in-out>.ng-leave-active{opacity:0}.toggle{display:inline-block}.toggle input{display:none}.toggle .track{position:relative;display:inline-block;box-sizing:border-box;width:54px;height:32px;border:solid 2px #ddd;border-radius:20px;background-color:#fff;cursor:pointer;transition:.4s ease}.toggle .handle{position:absolute;display:block;width:auto;height:auto;box-shadow:0 0 2px rgba(0,0,0,.5),0 4px 5px rgba(0,0,0,.25);border-radius:20px;background-color:#fff;left:0;top:0;bottom:0;right:20px;transition:.2s ease;transition-property:left,right;transition-delay:0s,.05s}.toggle :checked+.track{border-color:#4bd863;background-color:#ccc;box-shadow:inset 0 0 0 20px #4bd863;transition:.2s ease}.toggle :checked+.track .handle{background-color:#fff;right:0;left:20px;-webkit-transform:none;transition-delay:.05s,0s}

View File

Binary file not shown.

1054
dist/fonts/ionicons.svg vendored
View File

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 231 KiB

After

Width:  |  Height:  |  Size: 236 KiB

View File

Binary file not shown.

View File

Binary file not shown.

View File

@@ -2,7 +2,7 @@
* Copyright 2014 Drifty Co.
* http://drifty.com/
*
* Ionic, v0.9.19
* Ionic, v0.9.20
* A powerful HTML5 mobile app framework.
* http://ionicframework.com/
*
@@ -54,7 +54,6 @@ angular.module('ionic', [
// Angular deps
'ngAnimate',
'ngRoute',
'ngTouch',
'ngSanitize',
'ui.router'
@@ -65,7 +64,7 @@ angular.module('ionic', [
angular.module('ionic.ui.service.scrollDelegate', [])
.factory('ScrollDelegate', ['$rootScope', function($rootScope) {
.factory('$ionicScrollDelegate', ['$rootScope', '$timeout', function($rootScope, $timeout) {
return {
/**
* Trigger a scroll-to-top event on child scrollers.
@@ -129,7 +128,7 @@ angular.module('ionic.ui.service.scrollDelegate', [])
angular.module('ionic.ui.service.slideBoxDelegate', [])
.factory('SlideBoxDelegate', ['$rootScope', '$timeout', function($rootScope, $timeout) {
.factory('$ionicSlideBoxDelegate', ['$rootScope', '$timeout', function($rootScope, $timeout) {
return {
/**
* Trigger a slidebox to update and resize itself
@@ -154,10 +153,11 @@ angular.module('ionic.ui.service.slideBoxDelegate', [])
})(ionic);
;
angular.module('ionic.service.actionSheet', ['ionic.service.templateLoad', 'ionic.ui.actionSheet', 'ngAnimate'])
angular.module('ionic.service.actionSheet', ['ionic.service.templateLoad', 'ionic.service.platform', 'ionic.ui.actionSheet', 'ngAnimate'])
.factory('ActionSheet', ['$rootScope', '$document', '$compile', '$animate', '$timeout', 'TemplateLoader',
function($rootScope, $document, $compile, $animate, $timeout, TemplateLoader) {
.factory('$ionicActionSheet', ['$rootScope', '$document', '$compile', '$animate', '$timeout',
'$ionicTemplateLoader', '$ionicPlatform',
function($rootScope, $document, $compile, $animate, $timeout, $ionicTemplateLoader, $ionicPlatform) {
return {
/**
@@ -192,6 +192,17 @@ angular.module('ionic.service.actionSheet', ['ionic.service.templateLoad', 'ioni
});
};
var onHardwareBackButton = function() {
hideSheet();
};
scope.$on('$destroy', function() {
$ionicPlatform.offHardwareBackButton(onHardwareBackButton);
});
// Support Android back button to close
$ionicPlatform.onHardwareBackButton(onHardwareBackButton);
scope.cancel = function() {
hideSheet(true);
};
@@ -229,7 +240,7 @@ angular.module('ionic.service.actionSheet', ['ionic.service.templateLoad', 'ioni
;
angular.module('ionic.service.gesture', [])
.factory('Gesture', [function() {
.factory('$ionicGesture', [function() {
return {
on: function(eventType, cb, $element) {
return window.ionic.onGesture(eventType, cb, $element[0]);
@@ -242,7 +253,7 @@ angular.module('ionic.service.gesture', [])
;
angular.module('ionic.service.loading', ['ionic.ui.loading'])
.factory('Loading', ['$rootScope', '$document', '$compile', function($rootScope, $document, $compile) {
.factory('$ionicLoading', ['$rootScope', '$document', '$compile', function($rootScope, $document, $compile) {
return {
/**
* Load an action sheet with the given template string.
@@ -296,10 +307,10 @@ angular.module('ionic.service.loading', ['ionic.ui.loading'])
};
}]);
;
angular.module('ionic.service.modal', ['ionic.service.templateLoad', 'ngAnimate'])
angular.module('ionic.service.modal', ['ionic.service.templateLoad', 'ionic.service.platform', 'ngAnimate'])
.factory('Modal', ['$rootScope', '$document', '$compile', '$animate', '$q', 'TemplateLoader', function($rootScope, $document, $compile, $animate, $q, TemplateLoader) {
.factory('$ionicModal', ['$rootScope', '$document', '$compile', '$animate', '$q', '$timeout', '$ionicPlatform', '$ionicTemplateLoader', function($rootScope, $document, $compile, $animate, $q, $timeout, $ionicPlatform, $ionicTemplateLoader) {
var ModalView = ionic.views.Modal.inherit({
initialize: function(opts) {
ionic.views.Modal.prototype.initialize.call(this, opts);
@@ -310,11 +321,30 @@ angular.module('ionic.service.modal', ['ionic.service.templateLoad', 'ngAnimate'
var _this = this;
var element = angular.element(this.el);
if(!element.parent().length) {
angular.element($document[0].body).append(element);
element.addClass(this.animation);
$animate.enter(element, angular.element($document[0].body), null, function() {
});
ionic.views.Modal.prototype.show.call(_this);
} else {
$animate.addClass(element, this.animation, function() {
});
}
$animate.addClass(element, this.animation, function() {
});
if(!this.didInitEvents) {
var onHardwareBackButton = function() {
_this.hide();
};
_this.scope.$on('$destroy', function() {
$ionicPlatform.offHardwareBackButton(onHardwareBackButton);
});
// Support Android back button to close
$ionicPlatform.onHardwareBackButton(onHardwareBackButton);
this.didInitEvents = true;
}
},
// Hide the modal
hide: function() {
@@ -367,7 +397,7 @@ angular.module('ionic.service.modal', ['ionic.service.templateLoad', 'ngAnimate'
return modal;
},
fromTemplateUrl: function(url, cb, options) {
return TemplateLoader.load(url).then(function(templateString) {
return $ionicTemplateLoader.load(url).then(function(templateString) {
var modal = createModal(templateString, options || {});
cb ? cb(modal) : null;
return modal;
@@ -388,7 +418,7 @@ angular.module('ionic.service.platform', [])
* initializing some defaults that depend on the platform, such as the
* height of header bars on iOS 7.
*/
.provider('Platform', function() {
.provider('$ionicPlatform', function() {
var platform = 'web';
var isPlatformReady = false;
@@ -405,15 +435,7 @@ angular.module('ionic.service.platform', [])
// We need to do some stuff as soon as we know the platform,
// like adjust header margins for iOS 7, etc.
setTimeout(function afterReadyWait() {
if(isReady()) {
ionic.Platform.detect();
} else {
setTimeout(afterReadyWait, 50);
}
}, 10);
ionic.Platform.detect();
return {
@@ -478,7 +500,7 @@ angular.module('ionic.service.platform', [])
angular.module('ionic.service.popup', ['ionic.service.templateLoad'])
.factory('Popup', ['$rootScope', '$document', '$compile', 'TemplateLoader', function($rootScope, $document, $compile, TemplateLoader) {
.factory('$ionicPopup', ['$rootScope', '$document', '$compile', 'TemplateLoader', function($rootScope, $document, $compile, TemplateLoader) {
var getPopup = function() {
// Make sure there is only one loading element on the page at one point in time
@@ -535,7 +557,7 @@ angular.module('ionic.service.popup', ['ionic.service.templateLoad'])
;
angular.module('ionic.service.templateLoad', [])
.factory('TemplateLoader', ['$q', '$http', '$templateCache', function($q, $http, $templateCache) {
.factory('$ionicTemplateLoader', ['$q', '$http', '$templateCache', function($q, $http, $templateCache) {
return {
load: function(url) {
var deferred = $q.defer();
@@ -607,8 +629,8 @@ angular.module('ionic.service.view', ['ui.router'])
}])
.factory('ViewService', ['$rootScope', '$state', '$location', '$window', '$injector',
function( $rootScope, $state, $location, $window, $injector) {
.factory('$ionicViewService', ['$rootScope', '$state', '$location', '$window', '$injector',
function( $rootScope, $state, $location, $window, $injector) {
var $animate = $injector.has('$animate') ? $injector.get('$animate') : false;
var View = function(){};
@@ -757,17 +779,23 @@ angular.module('ionic.service.view', ['ui.router'])
hist.stack.push(viewHistory.histories[rsp.viewId]);
}
viewHistory.currentView = this._getView(rsp.viewId);
viewHistory.backView = this._getBackView(viewHistory.currentView);
viewHistory.forwardView = this._getForwardView(viewHistory.currentView);
this.setNavViews(rsp.viewId);
hist.cursor = viewHistory.currentView.index;
return rsp;
},
setNavViews: function(viewId) {
var viewHistory = $rootScope.$viewHistory;
viewHistory.currentView = this._getView(viewId);
viewHistory.backView = this._getBackView(viewHistory.currentView);
viewHistory.forwardView = this._getForwardView(viewHistory.currentView);
$rootScope.$broadcast('$viewHistory.historyChange', {
showBack: (viewHistory.backView && viewHistory.backView.historyId === viewHistory.currentView.historyId)
});
return rsp;
},
registerHistory: function(scope) {
@@ -894,6 +922,7 @@ angular.module('ionic.service.view', ['ui.router'])
if($animate && animationClass && opts.doAnimation !== false && opts.navDirection) {
// set the animation we're gonna use
this.setAnimationClass(opts.parentElement, animationClass, opts.navDirection);
opts.enteringElement.addClass('ng-enter');
// start the animations
if(opts.leavingElement) {
@@ -908,11 +937,6 @@ angular.module('ionic.service.view', ['ui.router'])
}
opts.parentElement.append(opts.enteringElement);
}
$rootScope.$broadcast('viewState.viewEnter', {
title: (opts.enteringScope ? opts.enteringScope.title : null),
navDirection: (opts.navDirection ? opts.navDirection : null)
});
function getAnimationClass(){
// go up the ancestors looking for an animation value
@@ -938,6 +962,31 @@ angular.module('ionic.service.view', ['ui.router'])
// make sure the reverse class isn't already added
element[0].classList.remove('reverse');
}
},
clearHistory: function() {
var historyId, x, view,
histories = $rootScope.$viewHistory.histories,
currentView = $rootScope.$viewHistory.currentView;
for(historyId in histories) {
if(histories[historyId].stack) {
histories[historyId].stack = [];
histories[historyId].cursor = -1;
}
if(currentView.historyId === historyId) {
currentView.backViewId = null;
currentView.forwardViewId = null;
histories[historyId].stack.push(currentView);
} else if(histories[historyId].destroy) {
histories[historyId].destroy();
}
}
this.setNavViews(currentView.viewId);
}
};
@@ -1000,17 +1049,17 @@ angular.module('ionic.ui.actionSheet', [])
angular.module('ionic.ui.header', ['ngAnimate'])
.directive('barHeader', ['ScrollDelegate', function(ScrollDelegate) {
.directive('barHeader', ['$ionicScrollDelegate', function($ionicScrollDelegate) {
return {
restrict: 'C',
link: function($scope, $element, $attr) {
// We want to scroll to top when the top of this element is clicked
ScrollDelegate.tapScrollToTop($element);
$ionicScrollDelegate.tapScrollToTop($element);
}
};
}])
.directive('headerBar', [function(ScrollDelegate) {
.directive('headerBar', ['$ionicScrollDelegate', function($ionicScrollDelegate) {
return {
restrict: 'E',
replace: true,
@@ -1152,11 +1201,11 @@ angular.module('ionic.ui.content', ['ionic.ui.service'])
// The content directive is a core scrollable content area
// that is part of many View hierarchies
.directive('content', ['$parse', '$timeout', 'Platform', 'ScrollDelegate', function($parse, $timeout, Platform, ScrollDelegate) {
.directive('content', ['$parse', '$timeout', '$ionicPlatform', '$ionicScrollDelegate', function($parse, $timeout, $ionicPlatform, $ionicScrollDelegate) {
return {
restrict: 'E',
replace: true,
template: '<div class="scroll-content"></div>',
template: '<div class="scroll-content"><div class="scroll" ng-transclude></div></div>',
transclude: true,
scope: {
onRefresh: '&',
@@ -1168,10 +1217,13 @@ angular.module('ionic.ui.content', ['ionic.ui.service'])
infiniteScrollDistance: '@',
hasBouncing: '@',
scroll: '@',
padding: '@',
hasScrollX: '@',
hasScrollY: '@',
scrollbarX: '@',
scrollbarY: '@',
startX: '@',
startY: '@',
scrollEventInterval: '@'
},
@@ -1180,33 +1232,21 @@ angular.module('ionic.ui.content', ['ionic.ui.service'])
if(attr.hasSubheader == "true") { element.addClass('has-subheader'); }
if(attr.hasFooter == "true") { element.addClass('has-footer'); }
if(attr.hasTabs == "true") { element.addClass('has-tabs'); }
if(attr.padding == "true") { element.find('div').addClass('padding'); }
return function link($scope, $element, $attr) {
var clone, sc, sv,
addedPadding = false,
c = $element.eq(0);
c = angular.element($element.children()[0]);
// If they want plain overflow scrolling, add that as a class
if($scope.scroll === "false") {
clone = transclude($scope.$parent);
$element.append(clone);
} else if(attr.overflowScroll === "true") {
c.addClass('overflow-scroll');
clone = transclude($scope.$parent);
$element.append(clone);
// No scrolling
return;
}
// If they want plain overflow scrolling, add that as a class
if(attr.overflowScroll === "true") {
$element.addClass('overflow-scroll');
} else {
sc = document.createElement('div');
sc.className = 'scroll';
if(attr.padding == "true") {
sc.className += ' padding';
addedPadding = true;
}
$element.append(sc);
// Pass the parent scope down to the child
clone = transclude($scope.$parent);
angular.element($element[0].firstElementChild).append(clone);
var refresher = $element[0].querySelector('.scroll-refresher');
var refresherHeight = refresher && refresher.clientHeight || 0;
@@ -1223,12 +1263,14 @@ angular.module('ionic.ui.content', ['ionic.ui.service'])
// Otherwise, supercharge this baby!
$timeout(function() {
var hasBouncing = $scope.$eval($scope.hasBouncing);
var enableBouncing = !Platform.is('Android') && hasBouncing !== false;
var enableBouncing = !$ionicPlatform.is('Android') && hasBouncing !== false;
// No bouncing by default for Android users, lest they take up pitchforks
// to our bouncing goodness
sv = new ionic.views.Scroll({
el: $element[0],
bouncing: enableBouncing,
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,
@@ -1257,7 +1299,7 @@ angular.module('ionic.ui.content', ['ionic.ui.service'])
}
// Register for scroll delegate event handling
ScrollDelegate.register($scope, $element);
$ionicScrollDelegate.register($scope, $element);
// Let child scopes access this
$scope.$parent.scrollView = sv;
@@ -1297,11 +1339,6 @@ angular.module('ionic.ui.content', ['ionic.ui.service'])
}
}
// if padding attribute is true, then add padding if it wasn't added to the .scroll
if(attr.padding == "true" && !addedPadding) {
c.addClass('padding');
}
};
}
};
@@ -1360,7 +1397,7 @@ angular.module('ionic.ui.list', ['ngAnimate'])
reorderIcon: '@'
},
template: '<div class="item item-complex" ng-class="itemClass">\
template: '<div class="item item-complex">\
<div class="item-edit" ng-if="deleteClick !== undefined">\
<button class="button button-icon icon" ng-class="deleteIconClass" ng-click="deleteClick()"></button>\
</div>\
@@ -1383,8 +1420,15 @@ angular.module('ionic.ui.list', ['ngAnimate'])
if(value) $scope.href = value.trim();
});
if(!$scope.itemType) {
$scope.itemType = $parentScope.itemType;
}
// Set this item's class, first from the item directive attr, and then the list attr if item not set
$scope.itemClass = $scope.itemType || $parentScope.itemType;
$element.addClass($scope.itemType || $parentScope.itemType);
$scope.itemClass = $scope.itemType;
// Decide if this item can do stuff, and follow a certain priority
// depending on where the value comes from
if(($attr.canDelete ? $scope.canDelete : $parentScope.canDelete) !== "false") {
@@ -1802,7 +1846,7 @@ angular.module('ionic.ui.sideMenu', ['ionic.service.gesture'])
};
})
.directive('sideMenuContent', ['$timeout', 'Gesture', function($timeout, Gesture) {
.directive('sideMenuContent', ['$timeout', '$ionicGesture', function($timeout, $ionicGesture) {
return {
restrict: 'AC',
require: '^sideMenus',
@@ -1842,10 +1886,10 @@ angular.module('ionic.ui.sideMenu', ['ionic.service.gesture'])
};
//var dragGesture = Gesture.on('drag', dragFn, $element);
var dragRightGesture = Gesture.on('dragright', dragFn, $element);
var dragLeftGesture = Gesture.on('dragleft', dragFn, $element);
var dragUpGesture = Gesture.on('dragup', dragVertFn, $element);
var dragDownGesture = Gesture.on('dragdown', dragVertFn, $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;
@@ -1855,7 +1899,7 @@ angular.module('ionic.ui.sideMenu', ['ionic.service.gesture'])
defaultPrevented = false;
};
var releaseGesture = Gesture.on('release', dragReleaseFn, $element);
var releaseGesture = $ionicGesture.on('release', dragReleaseFn, $element);
sideMenuCtrl.setContent({
onDrag: function(e) {},
@@ -1883,11 +1927,11 @@ angular.module('ionic.ui.sideMenu', ['ionic.service.gesture'])
// Cleanup
$scope.$on('$destroy', function() {
Gesture.off(dragLeftGesture, 'dragleft', dragFn);
Gesture.off(dragRightGesture, 'dragright', dragFn);
Gesture.off(dragUpGesture, 'dragup', dragFn);
Gesture.off(dragDownGesture, 'dragdown', dragFn);
Gesture.off(releaseGesture, 'release', dragReleaseFn);
$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);
});
};
}
@@ -1947,7 +1991,7 @@ angular.module('ionic.ui.slideBox', [])
* The internal controller for the slide box controller.
*/
.directive('slideBox', ['$timeout', '$compile', 'SlideBoxDelegate', function($timeout, $compile, SlideBoxDelegate) {
.directive('slideBox', ['$timeout', '$compile', '$ionicSlideBoxDelegate', function($timeout, $compile, $ionicSlideBoxDelegate) {
return {
restrict: 'E',
replace: true,
@@ -1958,7 +2002,7 @@ angular.module('ionic.ui.slideBox', [])
showPager: '@',
disableScroll: '@',
onSlideChanged: '&',
activeSlide: '='
activeSlide: '=?'
},
controller: ['$scope', '$element', function($scope, $element) {
var _this = this;
@@ -1971,6 +2015,7 @@ angular.module('ionic.ui.slideBox', [])
auto: slideInterval,
disableScroll: ($scope.$eval($scope.disableScroll) === true) || false,
continuous: continuous,
startSlide: $scope.activeSlide,
slidesChanged: function() {
$scope.currentSlide = slider.getPos();
@@ -2007,7 +2052,7 @@ angular.module('ionic.ui.slideBox', [])
$scope.$parent.slideBox = slider;
SlideBoxDelegate.register($scope, $element);
$ionicSlideBoxDelegate.register($scope, $element);
this.getNumSlides = function() {
return slider.getNumSlides();
@@ -2192,7 +2237,6 @@ angular.module('ionic.ui.tabs', ['ionic.service.view'])
});
$scope.$watch('activeAnimation', function(value) {
//$element.removeClass($scope.animation + ' ' + $scope.animation + '-reverse');
$element.addClass($scope.activeAnimation);
});
transclude($scope, function(cloned) {
@@ -2205,7 +2249,7 @@ angular.module('ionic.ui.tabs', ['ionic.service.view'])
}])
// Generic controller directive
.directive('tab', ['ViewService', '$rootScope', '$animate', '$parse', function(ViewService, $rootScope, $animate, $parse) {
.directive('tab', ['$ionicViewService', '$rootScope', '$parse', function($ionicViewService, $rootScope, $parse) {
return {
restrict: 'E',
require: '^tabs',
@@ -2216,7 +2260,7 @@ angular.module('ionic.ui.tabs', ['ionic.service.view'])
return function link($scope, $element, $attr, tabsCtrl) {
var childScope, childElement;
ViewService.registerHistory($scope);
$ionicViewService.registerHistory($scope);
$scope.title = $attr.title;
$scope.icon = $attr.icon;
@@ -2256,36 +2300,34 @@ angular.module('ionic.ui.tabs', ['ionic.service.view'])
$scope.$watch('isVisible', function(value) {
if(childElement) {
$animate.leave(childElement);
$scope.$broadcast('tab.hidden');
childElement = undefined;
childElement.remove();
childElement = null;
$rootScope.$broadcast('tab.hidden');
}
if(childScope) {
childScope.$destroy();
childScope = undefined;
childScope = null;
}
if(value) {
childScope = $scope.$new();
transclude(childScope, function(clone) {
childElement = clone;
clone.addClass('pane');
$animate.enter(clone, $element.parent(), $element);
$scope.$broadcast('tab.shown');
clone.removeAttr('title');
childElement = clone;
$element.parent().append(childElement);
});
$rootScope.$broadcast('tab.shown');
}
});
// check if it has a ui-view in it
// on link, check if it has a nav-view in it
transclude($scope.$new(), function(clone) {
var navViewEle = clone[0].getElementsByTagName("nav-view");
$scope.hasNavView = (navViewEle.length > 0);
if($scope.hasNavView) {
// this tab has a ui-view
$scope.navViewName = navViewEle[0].getAttribute('name');
if( ViewService.isCurrentStateNavView( $scope.navViewName ) ) {
if( $ionicViewService.isCurrentStateNavView( $scope.navViewName ) ) {
// this tab's ui-view is the current one, go to it!
tabsCtrl.select($scope.tabIndex);
}
@@ -2293,7 +2335,7 @@ angular.module('ionic.ui.tabs', ['ionic.service.view'])
});
$rootScope.$on('$stateChangeSuccess', function(value){
if( ViewService.isCurrentStateNavView($scope.navViewName) &&
if( $ionicViewService.isCurrentStateNavView($scope.navViewName) &&
$scope.tabIndex !== tabsCtrl.selectedIndex) {
tabsCtrl.select($scope.tabIndex);
}
@@ -2433,8 +2475,8 @@ angular.module('ionic.ui.viewState', ['ionic.service.view', 'ionic.service.gestu
/**
* Our Nav Bar directive which updates as the controller state changes.
*/
.directive('navBar', ['ViewService', '$rootScope', '$animate', '$compile',
function( ViewService, $rootScope, $animate, $compile) {
.directive('navBar', ['$ionicViewService', '$rootScope', '$animate', '$compile',
function( $ionicViewService, $rootScope, $animate, $compile) {
/**
* Perform an animation between one tab bar state and the next.
@@ -2478,7 +2520,7 @@ angular.module('ionic.ui.viewState', ['ionic.service.view', 'ionic.service.gestu
backButtonIcon: '@',
alignTitle: '@'
},
template: '<header class="bar bar-header nav-bar">'+//' ng-class="{invisible: !navController.navBar.isVisible}">' +
template: '<header class="bar bar-header nav-bar invisible">' +
'<div class="buttons"> ' +
'<button view-back class="button" ng-if="enableBackButton" ng-class="backButtonClass" ng-bind-html="backButtonLabel"></button>' +
'<button ng-click="button.tap($event)" ng-repeat="button in leftButtons" class="button no-animation {{button.type}}" ng-bind-html="button.content"></button>' +
@@ -2488,7 +2530,7 @@ angular.module('ionic.ui.viewState', ['ionic.service.view', 'ionic.service.gestu
'<button ng-click="button.tap($event)" ng-repeat="button in rightButtons" class="button no-animation {{button.type}}" ng-bind-html="button.content"></button>' +
'</div>' +
'</header>',
link: function($scope, $element, $attr, navCtrl) {
link: function($scope, $element, $attr) {
// Create the back button content and show/hide it based on scope settings
$scope.enableBackButton = true;
@@ -2497,8 +2539,13 @@ angular.module('ionic.ui.viewState', ['ionic.service.view', 'ionic.service.gestu
$scope.backButtonClass += ' icon ' + $attr.backButtonIcon;
}
// Store a reference to our nav controller
$scope.navController = navCtrl;
$rootScope.$on('viewState.showNavBar', function(e, showNavBar) {
if(showNavBar === false) {
$element[0].classList.add('invisible');
} else {
$element[0].classList.remove('invisible');
}
});
// Initialize our header bar view which will handle resizing and aligning our title labels
var hb = new ionic.views.HeaderBar({
@@ -2511,12 +2558,9 @@ angular.module('ionic.ui.viewState', ['ionic.service.view', 'ionic.service.gestu
$element.addClass($scope.type);
var updateHeaderData = function(data) {
var oldTitle = $scope.currentTitle;
$scope.oldTitle = oldTitle;
$scope.oldTitle = $scope.currentTitle;
if(typeof data.title !== 'undefined') {
$scope.currentTitle = data.title;
}
$scope.currentTitle = (data && data.title ? data.title : '');
$scope.leftButtons = data.leftButtons;
$scope.rightButtons = data.rightButtons;
@@ -2534,7 +2578,7 @@ angular.module('ionic.ui.viewState', ['ionic.service.view', 'ionic.service.gestu
$element[0].classList.remove('reverse');
}
animate($scope, $element, oldTitle, data, function() {
animate($scope, $element, $scope.oldTitle, data, function() {
hb.align();
});
} else {
@@ -2559,8 +2603,8 @@ angular.module('ionic.ui.viewState', ['ionic.service.view', 'ionic.service.gestu
}])
.directive('view', ['ViewService', '$rootScope', '$animate',
function( ViewService, $rootScope, $animate) {
.directive('view', ['$ionicViewService', '$rootScope', '$animate',
function( $ionicViewService, $rootScope, $animate) {
return {
restrict: 'EA',
priority: 1000,
@@ -2583,35 +2627,45 @@ angular.module('ionic.ui.viewState', ['ionic.service.view', 'ionic.service.gestu
tElement[0].removeAttribute('title');
return function link($scope, $element, $attr) {
$rootScope.$broadcast('viewState.viewEnter', {
title: $scope.title,
navDirection: $scope.$navDirection || $scope.$parent.$navDirection
});
// Should we hide a back button when this tab is shown
$scope.hideBackButton = $scope.$eval($scope.hideBackButton);
$scope.hideNavBar = $scope.$eval($scope.hideNavBar);
if($scope.hideBackButton === true) {
$scope.$emit('viewState.hideBackButton');
} else {
$scope.$emit('viewState.showBackButton');
if($scope.hideBackButton) {
$rootScope.$broadcast('viewState.showBackButton', false);
}
// Should the nav bar be hidden for this view or not?
$rootScope.$broadcast('viewState.showNavBar', ($scope.hideNavBar !== 'true') );
// watch for changes in the left buttons
$scope.$watch('leftButtons', function(value) {
var deregLeftButtons = $scope.$watch('leftButtons', function(value) {
$scope.$emit('viewState.leftButtonsChanged', $scope.leftButtons);
});
$scope.$watch('rightButtons', function(val) {
var deregRightButtons = $scope.$watch('rightButtons', function(val) {
$scope.$emit('viewState.rightButtonsChanged', $scope.rightButtons);
});
$scope.$on('$destroy', function(){
// deregister on destroy
deregLeftButtons();
deregRightButtons();
});
};
}
};
}])
.directive('viewBack', ['ViewService', '$rootScope', function(ViewService, $rootScope) {
.directive('viewBack', ['$ionicViewService', '$rootScope', function($ionicViewService, $rootScope) {
var goBack = function(e) {
var backView = ViewService.getBackView();
var backView = $ionicViewService.getBackView();
backView && backView.go();
e.alreadyHandled = true;
return false;
@@ -2625,12 +2679,20 @@ angular.module('ionic.ui.viewState', ['ionic.service.view', 'ionic.service.gestu
return function link($scope, $element) {
$element.bind('click', goBack);
$rootScope.$on('$viewHistory.historyChange', function(e, data) {
if(data.showBack) {
$scope.showButton = function(val) {
if(val) {
$element[0].classList.remove('hide');
} else {
$element[0].classList.add('hide');
}
};
$rootScope.$on('$viewHistory.historyChange', function(e, data) {
$scope.showButton(data.showBack);
});
$rootScope.$on('viewState.showBackButton', function(e, data) {
$scope.showButton(data);
});
};
@@ -2640,8 +2702,8 @@ angular.module('ionic.ui.viewState', ['ionic.service.view', 'ionic.service.gestu
}])
.directive('navView', ['ViewService', '$state', '$anchorScroll', '$compile', '$controller', '$animate',
function( ViewService, $state, $anchorScroll, $compile, $controller, $animate) {
.directive('navView', ['$ionicViewService', '$state', '$anchorScroll', '$compile', '$controller', '$animate',
function( $ionicViewService, $state, $anchorScroll, $compile, $controller, $animate) {
var viewIsUpdating = false;
var animation;
@@ -2706,7 +2768,7 @@ angular.module('ionic.ui.viewState', ['ionic.service.view', 'ionic.service.gestu
var registerData = {};
if(currentElement[0].tagName !== 'TABS') {
// the tabs directive shouldn't register in the view history (its tab will)
registerData = ViewService.register(scope);
registerData = $ionicViewService.register(scope);
transitionOptions.navDirection = registerData.navDirection;
}
@@ -2717,6 +2779,7 @@ angular.module('ionic.ui.viewState', ['ionic.service.view', 'ionic.service.gestu
current = $state.current;
viewScope = current.scope = scope.$new();
viewScope.$navDirection = transitionOptions.navDirection;
if (locals.$$controller) {
locals.$scope = viewScope;
@@ -2734,11 +2797,11 @@ angular.module('ionic.ui.viewState', ['ionic.service.view', 'ionic.service.gestu
viewScope.$eval(onloadExp);
viewScope.animation = animation;
transitionOptions.enteringScope = viewScope.$$childHead;
transitionOptions.enteringScope = viewScope;
transitionOptions.enteringElement = currentElement;
}
ViewService.transition(transitionOptions);
$ionicViewService.transition(transitionOptions);
}
}
};
@@ -2746,7 +2809,8 @@ angular.module('ionic.ui.viewState', ['ionic.service.view', 'ionic.service.gestu
}]);
})();;
})();
;
(function() {
'use strict';

View File

File diff suppressed because one or more lines are too long

48
dist/js/ionic.js vendored
View File

@@ -2,7 +2,7 @@
* Copyright 2014 Drifty Co.
* http://drifty.com/
*
* Ionic, v0.9.19
* Ionic, v0.9.20
* A powerful HTML5 mobile app framework.
* http://ionicframework.com/
*
@@ -16,7 +16,7 @@
window.ionic = {
controllers: {},
views: {},
version: '0.9.19'
version: '0.9.20'
};;
(function(ionic) {
@@ -1737,25 +1737,34 @@ window.ionic = {
(function(ionic) {
ionic.Platform = {
detect: function() {
var platforms = [];
var domReady = function() {
// run when the DOM is ready
document.addEventListener("deviceready", deviceReady, false);
document.removeEventListener("DOMContentLoaded", domReady, false);
};
document.addEventListener("DOMContentLoaded", domReady, false);
this._checkPlatforms(platforms);
var deviceReady = function() {
// run when cordova is fully loaded
var platforms = [];
ionic.Platform._checkPlatforms(platforms);
var classify = function() {
if(!document.body) { return; }
for(var i = 0; i < platforms.length; i++) {
document.body.classList.add('platform-' + platforms[i]);
if(platforms.length) {
// only change the body class if we got platform info
var bodyClass = document.body.className;
for(var i = 0; i < platforms.length; i++) {
bodyClass += ' platform-' + platforms[i];
}
document.body.className = bodyClass;
}
document.removeEventListener("deviceready", deviceReady, false);
};
document.addEventListener( "DOMContentLoaded", function(){
classify();
});
classify();
},
_checkPlatforms: function(platforms) {
if(this.isCordova()) {
platforms.push('cordova');
@@ -1769,6 +1778,9 @@ window.ionic = {
if(this.isAndroid()) {
platforms.push('android');
}
// Return whether we detected anything
return (platforms.length > 0);
},
// Check if we are running in Cordova, which will have
@@ -1794,7 +1806,7 @@ window.ionic = {
// Check if the platform is the one detected by cordova
is: function(type) {
if(window.device) {
if(window.device && window.device.platform) {
return window.device.platform === type || window.device.platform.toLowerCase() === type;
}
@@ -2380,6 +2392,9 @@ ionic.views.Scroll = ionic.views.View.inherit({
scrollingY: true,
scrollbarY: true,
startX: 0,
startY: 0,
/** The minimum size the scrollbars scale to while scrolling */
minScrollbarSizeX: 5,
minScrollbarSizeY: 5,
@@ -2459,6 +2474,9 @@ ionic.views.Scroll = ionic.views.View.inherit({
});
};
this.__scrollLeft = this.options.startX;
this.__scrollTop = this.options.startY;
// Get the render update function, initialize event handlers,
// and calculate the size of the scroll container
this.__callback = this.getRenderFn();

View File

File diff suppressed because one or more lines are too long

View File

@@ -37,7 +37,7 @@
back-button-icon="ion-arrow-left-c"></nav-bar>
<!-- where the content of each page will be rendered -->
<nav-view animation="slide-left-right"></ui-view>
<nav-view animation="slide-left-right"></nav-view>
<!--

View File

@@ -3,17 +3,17 @@
angular.module('ionic.ui.header', ['ngAnimate'])
.directive('barHeader', ['ScrollDelegate', function(ScrollDelegate) {
.directive('barHeader', ['$ionicScrollDelegate', function($ionicScrollDelegate) {
return {
restrict: 'C',
link: function($scope, $element, $attr) {
// We want to scroll to top when the top of this element is clicked
ScrollDelegate.tapScrollToTop($element);
$ionicScrollDelegate.tapScrollToTop($element);
}
};
}])
.directive('headerBar', [function(ScrollDelegate) {
.directive('headerBar', ['$ionicScrollDelegate', function($ionicScrollDelegate) {
return {
restrict: 'E',
replace: true,

View File

@@ -18,11 +18,11 @@ angular.module('ionic.ui.content', ['ionic.ui.service'])
// The content directive is a core scrollable content area
// that is part of many View hierarchies
.directive('content', ['$parse', '$timeout', 'Platform', 'ScrollDelegate', function($parse, $timeout, Platform, ScrollDelegate) {
.directive('content', ['$parse', '$timeout', '$ionicPlatform', '$ionicScrollDelegate', function($parse, $timeout, $ionicPlatform, $ionicScrollDelegate) {
return {
restrict: 'E',
replace: true,
template: '<div class="scroll-content"></div>',
template: '<div class="scroll-content"><div class="scroll" ng-transclude></div></div>',
transclude: true,
scope: {
onRefresh: '&',
@@ -34,10 +34,13 @@ angular.module('ionic.ui.content', ['ionic.ui.service'])
infiniteScrollDistance: '@',
hasBouncing: '@',
scroll: '@',
padding: '@',
hasScrollX: '@',
hasScrollY: '@',
scrollbarX: '@',
scrollbarY: '@',
startX: '@',
startY: '@',
scrollEventInterval: '@'
},
@@ -46,33 +49,21 @@ angular.module('ionic.ui.content', ['ionic.ui.service'])
if(attr.hasSubheader == "true") { element.addClass('has-subheader'); }
if(attr.hasFooter == "true") { element.addClass('has-footer'); }
if(attr.hasTabs == "true") { element.addClass('has-tabs'); }
if(attr.padding == "true") { element.find('div').addClass('padding'); }
return function link($scope, $element, $attr) {
var clone, sc, sv,
addedPadding = false,
c = $element.eq(0);
c = angular.element($element.children()[0]);
// If they want plain overflow scrolling, add that as a class
if($scope.scroll === "false") {
clone = transclude($scope.$parent);
$element.append(clone);
} else if(attr.overflowScroll === "true") {
c.addClass('overflow-scroll');
clone = transclude($scope.$parent);
$element.append(clone);
// No scrolling
return;
}
// If they want plain overflow scrolling, add that as a class
if(attr.overflowScroll === "true") {
$element.addClass('overflow-scroll');
} else {
sc = document.createElement('div');
sc.className = 'scroll';
if(attr.padding == "true") {
sc.className += ' padding';
addedPadding = true;
}
$element.append(sc);
// Pass the parent scope down to the child
clone = transclude($scope.$parent);
angular.element($element[0].firstElementChild).append(clone);
var refresher = $element[0].querySelector('.scroll-refresher');
var refresherHeight = refresher && refresher.clientHeight || 0;
@@ -89,12 +80,14 @@ angular.module('ionic.ui.content', ['ionic.ui.service'])
// Otherwise, supercharge this baby!
$timeout(function() {
var hasBouncing = $scope.$eval($scope.hasBouncing);
var enableBouncing = !Platform.is('Android') && hasBouncing !== false;
var enableBouncing = !$ionicPlatform.is('Android') && hasBouncing !== false;
// No bouncing by default for Android users, lest they take up pitchforks
// to our bouncing goodness
sv = new ionic.views.Scroll({
el: $element[0],
bouncing: enableBouncing,
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,
@@ -123,7 +116,7 @@ angular.module('ionic.ui.content', ['ionic.ui.service'])
}
// Register for scroll delegate event handling
ScrollDelegate.register($scope, $element);
$ionicScrollDelegate.register($scope, $element);
// Let child scopes access this
$scope.$parent.scrollView = sv;
@@ -163,11 +156,6 @@ angular.module('ionic.ui.content', ['ionic.ui.service'])
}
}
// if padding attribute is true, then add padding if it wasn't added to the .scroll
if(attr.padding == "true" && !addedPadding) {
c.addClass('padding');
}
};
}
};

View File

@@ -22,7 +22,7 @@ angular.module('ionic.ui.list', ['ngAnimate'])
reorderIcon: '@'
},
template: '<div class="item item-complex" ng-class="itemClass">\
template: '<div class="item item-complex">\
<div class="item-edit" ng-if="deleteClick !== undefined">\
<button class="button button-icon icon" ng-class="deleteIconClass" ng-click="deleteClick()"></button>\
</div>\
@@ -45,8 +45,15 @@ angular.module('ionic.ui.list', ['ngAnimate'])
if(value) $scope.href = value.trim();
});
if(!$scope.itemType) {
$scope.itemType = $parentScope.itemType;
}
// Set this item's class, first from the item directive attr, and then the list attr if item not set
$scope.itemClass = $scope.itemType || $parentScope.itemType;
$element.addClass($scope.itemType || $parentScope.itemType);
$scope.itemClass = $scope.itemType;
// Decide if this item can do stuff, and follow a certain priority
// depending on where the value comes from
if(($attr.canDelete ? $scope.canDelete : $parentScope.canDelete) !== "false") {

View File

@@ -45,7 +45,7 @@ angular.module('ionic.ui.sideMenu', ['ionic.service.gesture'])
};
})
.directive('sideMenuContent', ['$timeout', 'Gesture', function($timeout, Gesture) {
.directive('sideMenuContent', ['$timeout', '$ionicGesture', function($timeout, $ionicGesture) {
return {
restrict: 'AC',
require: '^sideMenus',
@@ -85,10 +85,10 @@ angular.module('ionic.ui.sideMenu', ['ionic.service.gesture'])
};
//var dragGesture = Gesture.on('drag', dragFn, $element);
var dragRightGesture = Gesture.on('dragright', dragFn, $element);
var dragLeftGesture = Gesture.on('dragleft', dragFn, $element);
var dragUpGesture = Gesture.on('dragup', dragVertFn, $element);
var dragDownGesture = Gesture.on('dragdown', dragVertFn, $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;
@@ -98,7 +98,7 @@ angular.module('ionic.ui.sideMenu', ['ionic.service.gesture'])
defaultPrevented = false;
};
var releaseGesture = Gesture.on('release', dragReleaseFn, $element);
var releaseGesture = $ionicGesture.on('release', dragReleaseFn, $element);
sideMenuCtrl.setContent({
onDrag: function(e) {},
@@ -126,11 +126,11 @@ angular.module('ionic.ui.sideMenu', ['ionic.service.gesture'])
// Cleanup
$scope.$on('$destroy', function() {
Gesture.off(dragLeftGesture, 'dragleft', dragFn);
Gesture.off(dragRightGesture, 'dragright', dragFn);
Gesture.off(dragUpGesture, 'dragup', dragFn);
Gesture.off(dragDownGesture, 'dragdown', dragFn);
Gesture.off(releaseGesture, 'release', dragReleaseFn);
$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);
});
};
}

View File

@@ -13,7 +13,7 @@ angular.module('ionic.ui.slideBox', [])
* The internal controller for the slide box controller.
*/
.directive('slideBox', ['$timeout', '$compile', 'SlideBoxDelegate', function($timeout, $compile, SlideBoxDelegate) {
.directive('slideBox', ['$timeout', '$compile', '$ionicSlideBoxDelegate', function($timeout, $compile, $ionicSlideBoxDelegate) {
return {
restrict: 'E',
replace: true,
@@ -24,7 +24,7 @@ angular.module('ionic.ui.slideBox', [])
showPager: '@',
disableScroll: '@',
onSlideChanged: '&',
activeSlide: '='
activeSlide: '=?'
},
controller: ['$scope', '$element', function($scope, $element) {
var _this = this;
@@ -37,6 +37,7 @@ angular.module('ionic.ui.slideBox', [])
auto: slideInterval,
disableScroll: ($scope.$eval($scope.disableScroll) === true) || false,
continuous: continuous,
startSlide: $scope.activeSlide,
slidesChanged: function() {
$scope.currentSlide = slider.getPos();
@@ -73,7 +74,7 @@ angular.module('ionic.ui.slideBox', [])
$scope.$parent.slideBox = slider;
SlideBoxDelegate.register($scope, $element);
$ionicSlideBoxDelegate.register($scope, $element);
this.getNumSlides = function() {
return slider.getNumSlides();

View File

@@ -112,7 +112,6 @@ angular.module('ionic.ui.tabs', ['ionic.service.view'])
});
$scope.$watch('activeAnimation', function(value) {
//$element.removeClass($scope.animation + ' ' + $scope.animation + '-reverse');
$element.addClass($scope.activeAnimation);
});
transclude($scope, function(cloned) {
@@ -125,7 +124,7 @@ angular.module('ionic.ui.tabs', ['ionic.service.view'])
}])
// Generic controller directive
.directive('tab', ['ViewService', '$rootScope', '$animate', '$parse', function(ViewService, $rootScope, $animate, $parse) {
.directive('tab', ['$ionicViewService', '$rootScope', '$parse', function($ionicViewService, $rootScope, $parse) {
return {
restrict: 'E',
require: '^tabs',
@@ -136,7 +135,7 @@ angular.module('ionic.ui.tabs', ['ionic.service.view'])
return function link($scope, $element, $attr, tabsCtrl) {
var childScope, childElement;
ViewService.registerHistory($scope);
$ionicViewService.registerHistory($scope);
$scope.title = $attr.title;
$scope.icon = $attr.icon;
@@ -176,36 +175,34 @@ angular.module('ionic.ui.tabs', ['ionic.service.view'])
$scope.$watch('isVisible', function(value) {
if(childElement) {
$animate.leave(childElement);
$scope.$broadcast('tab.hidden');
childElement = undefined;
childElement.remove();
childElement = null;
$rootScope.$broadcast('tab.hidden');
}
if(childScope) {
childScope.$destroy();
childScope = undefined;
childScope = null;
}
if(value) {
childScope = $scope.$new();
transclude(childScope, function(clone) {
childElement = clone;
clone.addClass('pane');
$animate.enter(clone, $element.parent(), $element);
$scope.$broadcast('tab.shown');
clone.removeAttr('title');
childElement = clone;
$element.parent().append(childElement);
});
$rootScope.$broadcast('tab.shown');
}
});
// check if it has a ui-view in it
// on link, check if it has a nav-view in it
transclude($scope.$new(), function(clone) {
var navViewEle = clone[0].getElementsByTagName("nav-view");
$scope.hasNavView = (navViewEle.length > 0);
if($scope.hasNavView) {
// this tab has a ui-view
$scope.navViewName = navViewEle[0].getAttribute('name');
if( ViewService.isCurrentStateNavView( $scope.navViewName ) ) {
if( $ionicViewService.isCurrentStateNavView( $scope.navViewName ) ) {
// this tab's ui-view is the current one, go to it!
tabsCtrl.select($scope.tabIndex);
}
@@ -213,7 +210,7 @@ angular.module('ionic.ui.tabs', ['ionic.service.view'])
});
$rootScope.$on('$stateChangeSuccess', function(value){
if( ViewService.isCurrentStateNavView($scope.navViewName) &&
if( $ionicViewService.isCurrentStateNavView($scope.navViewName) &&
$scope.tabIndex !== tabsCtrl.selectedIndex) {
tabsCtrl.select($scope.tabIndex);
}

View File

@@ -22,8 +22,8 @@ angular.module('ionic.ui.viewState', ['ionic.service.view', 'ionic.service.gestu
/**
* Our Nav Bar directive which updates as the controller state changes.
*/
.directive('navBar', ['ViewService', '$rootScope', '$animate', '$compile',
function( ViewService, $rootScope, $animate, $compile) {
.directive('navBar', ['$ionicViewService', '$rootScope', '$animate', '$compile',
function( $ionicViewService, $rootScope, $animate, $compile) {
/**
* Perform an animation between one tab bar state and the next.
@@ -67,7 +67,7 @@ angular.module('ionic.ui.viewState', ['ionic.service.view', 'ionic.service.gestu
backButtonIcon: '@',
alignTitle: '@'
},
template: '<header class="bar bar-header nav-bar">'+//' ng-class="{invisible: !navController.navBar.isVisible}">' +
template: '<header class="bar bar-header nav-bar invisible">' +
'<div class="buttons"> ' +
'<button view-back class="button" ng-if="enableBackButton" ng-class="backButtonClass" ng-bind-html="backButtonLabel"></button>' +
'<button ng-click="button.tap($event)" ng-repeat="button in leftButtons" class="button no-animation {{button.type}}" ng-bind-html="button.content"></button>' +
@@ -77,7 +77,7 @@ angular.module('ionic.ui.viewState', ['ionic.service.view', 'ionic.service.gestu
'<button ng-click="button.tap($event)" ng-repeat="button in rightButtons" class="button no-animation {{button.type}}" ng-bind-html="button.content"></button>' +
'</div>' +
'</header>',
link: function($scope, $element, $attr, navCtrl) {
link: function($scope, $element, $attr) {
// Create the back button content and show/hide it based on scope settings
$scope.enableBackButton = true;
@@ -86,8 +86,13 @@ angular.module('ionic.ui.viewState', ['ionic.service.view', 'ionic.service.gestu
$scope.backButtonClass += ' icon ' + $attr.backButtonIcon;
}
// Store a reference to our nav controller
$scope.navController = navCtrl;
$rootScope.$on('viewState.showNavBar', function(e, showNavBar) {
if(showNavBar === false) {
$element[0].classList.add('invisible');
} else {
$element[0].classList.remove('invisible');
}
});
// Initialize our header bar view which will handle resizing and aligning our title labels
var hb = new ionic.views.HeaderBar({
@@ -100,12 +105,9 @@ angular.module('ionic.ui.viewState', ['ionic.service.view', 'ionic.service.gestu
$element.addClass($scope.type);
var updateHeaderData = function(data) {
var oldTitle = $scope.currentTitle;
$scope.oldTitle = oldTitle;
$scope.oldTitle = $scope.currentTitle;
if(typeof data.title !== 'undefined') {
$scope.currentTitle = data.title;
}
$scope.currentTitle = (data && data.title ? data.title : '');
$scope.leftButtons = data.leftButtons;
$scope.rightButtons = data.rightButtons;
@@ -123,7 +125,7 @@ angular.module('ionic.ui.viewState', ['ionic.service.view', 'ionic.service.gestu
$element[0].classList.remove('reverse');
}
animate($scope, $element, oldTitle, data, function() {
animate($scope, $element, $scope.oldTitle, data, function() {
hb.align();
});
} else {
@@ -148,8 +150,8 @@ angular.module('ionic.ui.viewState', ['ionic.service.view', 'ionic.service.gestu
}])
.directive('view', ['ViewService', '$rootScope', '$animate',
function( ViewService, $rootScope, $animate) {
.directive('view', ['$ionicViewService', '$rootScope', '$animate',
function( $ionicViewService, $rootScope, $animate) {
return {
restrict: 'EA',
priority: 1000,
@@ -172,35 +174,45 @@ angular.module('ionic.ui.viewState', ['ionic.service.view', 'ionic.service.gestu
tElement[0].removeAttribute('title');
return function link($scope, $element, $attr) {
$rootScope.$broadcast('viewState.viewEnter', {
title: $scope.title,
navDirection: $scope.$navDirection || $scope.$parent.$navDirection
});
// Should we hide a back button when this tab is shown
$scope.hideBackButton = $scope.$eval($scope.hideBackButton);
$scope.hideNavBar = $scope.$eval($scope.hideNavBar);
if($scope.hideBackButton === true) {
$scope.$emit('viewState.hideBackButton');
} else {
$scope.$emit('viewState.showBackButton');
if($scope.hideBackButton) {
$rootScope.$broadcast('viewState.showBackButton', false);
}
// Should the nav bar be hidden for this view or not?
$rootScope.$broadcast('viewState.showNavBar', ($scope.hideNavBar !== 'true') );
// watch for changes in the left buttons
$scope.$watch('leftButtons', function(value) {
var deregLeftButtons = $scope.$watch('leftButtons', function(value) {
$scope.$emit('viewState.leftButtonsChanged', $scope.leftButtons);
});
$scope.$watch('rightButtons', function(val) {
var deregRightButtons = $scope.$watch('rightButtons', function(val) {
$scope.$emit('viewState.rightButtonsChanged', $scope.rightButtons);
});
$scope.$on('$destroy', function(){
// deregister on destroy
deregLeftButtons();
deregRightButtons();
});
};
}
};
}])
.directive('viewBack', ['ViewService', '$rootScope', function(ViewService, $rootScope) {
.directive('viewBack', ['$ionicViewService', '$rootScope', function($ionicViewService, $rootScope) {
var goBack = function(e) {
var backView = ViewService.getBackView();
var backView = $ionicViewService.getBackView();
backView && backView.go();
e.alreadyHandled = true;
return false;
@@ -214,12 +226,20 @@ angular.module('ionic.ui.viewState', ['ionic.service.view', 'ionic.service.gestu
return function link($scope, $element) {
$element.bind('click', goBack);
$rootScope.$on('$viewHistory.historyChange', function(e, data) {
if(data.showBack) {
$scope.showButton = function(val) {
if(val) {
$element[0].classList.remove('hide');
} else {
$element[0].classList.add('hide');
}
};
$rootScope.$on('$viewHistory.historyChange', function(e, data) {
$scope.showButton(data.showBack);
});
$rootScope.$on('viewState.showBackButton', function(e, data) {
$scope.showButton(data);
});
};
@@ -229,8 +249,8 @@ angular.module('ionic.ui.viewState', ['ionic.service.view', 'ionic.service.gestu
}])
.directive('navView', ['ViewService', '$state', '$anchorScroll', '$compile', '$controller', '$animate',
function( ViewService, $state, $anchorScroll, $compile, $controller, $animate) {
.directive('navView', ['$ionicViewService', '$state', '$anchorScroll', '$compile', '$controller', '$animate',
function( $ionicViewService, $state, $anchorScroll, $compile, $controller, $animate) {
var viewIsUpdating = false;
var animation;
@@ -295,7 +315,7 @@ angular.module('ionic.ui.viewState', ['ionic.service.view', 'ionic.service.gestu
var registerData = {};
if(currentElement[0].tagName !== 'TABS') {
// the tabs directive shouldn't register in the view history (its tab will)
registerData = ViewService.register(scope);
registerData = $ionicViewService.register(scope);
transitionOptions.navDirection = registerData.navDirection;
}
@@ -306,6 +326,7 @@ angular.module('ionic.ui.viewState', ['ionic.service.view', 'ionic.service.gestu
current = $state.current;
viewScope = current.scope = scope.$new();
viewScope.$navDirection = transitionOptions.navDirection;
if (locals.$$controller) {
locals.$scope = viewScope;
@@ -323,11 +344,11 @@ angular.module('ionic.ui.viewState', ['ionic.service.view', 'ionic.service.gestu
viewScope.$eval(onloadExp);
viewScope.animation = animation;
transitionOptions.enteringScope = viewScope.$$childHead;
transitionOptions.enteringScope = viewScope;
transitionOptions.enteringElement = currentElement;
}
ViewService.transition(transitionOptions);
$ionicViewService.transition(transitionOptions);
}
}
};
@@ -335,4 +356,4 @@ angular.module('ionic.ui.viewState', ['ionic.service.view', 'ionic.service.gestu
}]);
})();
})();

View File

@@ -41,7 +41,6 @@ angular.module('ionic', [
// Angular deps
'ngAnimate',
'ngRoute',
'ngTouch',
'ngSanitize',
'ui.router'

View File

@@ -3,7 +3,7 @@
angular.module('ionic.ui.service.scrollDelegate', [])
.factory('ScrollDelegate', ['$rootScope', function($rootScope) {
.factory('$ionicScrollDelegate', ['$rootScope', '$timeout', function($rootScope, $timeout) {
return {
/**
* Trigger a scroll-to-top event on child scrollers.

View File

@@ -3,7 +3,7 @@
angular.module('ionic.ui.service.slideBoxDelegate', [])
.factory('SlideBoxDelegate', ['$rootScope', '$timeout', function($rootScope, $timeout) {
.factory('$ionicSlideBoxDelegate', ['$rootScope', '$timeout', function($rootScope, $timeout) {
return {
/**
* Trigger a slidebox to update and resize itself

View File

@@ -1,7 +1,8 @@
angular.module('ionic.service.actionSheet', ['ionic.service.templateLoad', 'ionic.ui.actionSheet', 'ngAnimate'])
angular.module('ionic.service.actionSheet', ['ionic.service.templateLoad', 'ionic.service.platform', 'ionic.ui.actionSheet', 'ngAnimate'])
.factory('ActionSheet', ['$rootScope', '$document', '$compile', '$animate', '$timeout', 'TemplateLoader',
function($rootScope, $document, $compile, $animate, $timeout, TemplateLoader) {
.factory('$ionicActionSheet', ['$rootScope', '$document', '$compile', '$animate', '$timeout',
'$ionicTemplateLoader', '$ionicPlatform',
function($rootScope, $document, $compile, $animate, $timeout, $ionicTemplateLoader, $ionicPlatform) {
return {
/**
@@ -36,6 +37,17 @@ angular.module('ionic.service.actionSheet', ['ionic.service.templateLoad', 'ioni
});
};
var onHardwareBackButton = function() {
hideSheet();
};
scope.$on('$destroy', function() {
$ionicPlatform.offHardwareBackButton(onHardwareBackButton);
});
// Support Android back button to close
$ionicPlatform.onHardwareBackButton(onHardwareBackButton);
scope.cancel = function() {
hideSheet(true);
};

View File

@@ -1,6 +1,6 @@
angular.module('ionic.service.gesture', [])
.factory('Gesture', [function() {
.factory('$ionicGesture', [function() {
return {
on: function(eventType, cb, $element) {
return window.ionic.onGesture(eventType, cb, $element[0]);

View File

@@ -1,6 +1,6 @@
angular.module('ionic.service.loading', ['ionic.ui.loading'])
.factory('Loading', ['$rootScope', '$document', '$compile', function($rootScope, $document, $compile) {
.factory('$ionicLoading', ['$rootScope', '$document', '$compile', function($rootScope, $document, $compile) {
return {
/**
* Load an action sheet with the given template string.

View File

@@ -1,7 +1,7 @@
angular.module('ionic.service.modal', ['ionic.service.templateLoad', 'ngAnimate'])
angular.module('ionic.service.modal', ['ionic.service.templateLoad', 'ionic.service.platform', 'ngAnimate'])
.factory('Modal', ['$rootScope', '$document', '$compile', '$animate', '$q', 'TemplateLoader', function($rootScope, $document, $compile, $animate, $q, TemplateLoader) {
.factory('$ionicModal', ['$rootScope', '$document', '$compile', '$animate', '$q', '$timeout', '$ionicPlatform', '$ionicTemplateLoader', function($rootScope, $document, $compile, $animate, $q, $timeout, $ionicPlatform, $ionicTemplateLoader) {
var ModalView = ionic.views.Modal.inherit({
initialize: function(opts) {
ionic.views.Modal.prototype.initialize.call(this, opts);
@@ -12,11 +12,30 @@ angular.module('ionic.service.modal', ['ionic.service.templateLoad', 'ngAnimate'
var _this = this;
var element = angular.element(this.el);
if(!element.parent().length) {
angular.element($document[0].body).append(element);
element.addClass(this.animation);
$animate.enter(element, angular.element($document[0].body), null, function() {
});
ionic.views.Modal.prototype.show.call(_this);
} else {
$animate.addClass(element, this.animation, function() {
});
}
$animate.addClass(element, this.animation, function() {
});
if(!this.didInitEvents) {
var onHardwareBackButton = function() {
_this.hide();
};
_this.scope.$on('$destroy', function() {
$ionicPlatform.offHardwareBackButton(onHardwareBackButton);
});
// Support Android back button to close
$ionicPlatform.onHardwareBackButton(onHardwareBackButton);
this.didInitEvents = true;
}
},
// Hide the modal
hide: function() {
@@ -69,7 +88,7 @@ angular.module('ionic.service.modal', ['ionic.service.templateLoad', 'ngAnimate'
return modal;
},
fromTemplateUrl: function(url, cb, options) {
return TemplateLoader.load(url).then(function(templateString) {
return $ionicTemplateLoader.load(url).then(function(templateString) {
var modal = createModal(templateString, options || {});
cb ? cb(modal) : null;
return modal;

View File

@@ -10,7 +10,7 @@ angular.module('ionic.service.platform', [])
* initializing some defaults that depend on the platform, such as the
* height of header bars on iOS 7.
*/
.provider('Platform', function() {
.provider('$ionicPlatform', function() {
var platform = 'web';
var isPlatformReady = false;
@@ -27,15 +27,7 @@ angular.module('ionic.service.platform', [])
// We need to do some stuff as soon as we know the platform,
// like adjust header margins for iOS 7, etc.
setTimeout(function afterReadyWait() {
if(isReady()) {
ionic.Platform.detect();
} else {
setTimeout(afterReadyWait, 50);
}
}, 10);
ionic.Platform.detect();
return {

View File

@@ -1,7 +1,7 @@
angular.module('ionic.service.popup', ['ionic.service.templateLoad'])
.factory('Popup', ['$rootScope', '$document', '$compile', 'TemplateLoader', function($rootScope, $document, $compile, TemplateLoader) {
.factory('$ionicPopup', ['$rootScope', '$document', '$compile', 'TemplateLoader', function($rootScope, $document, $compile, TemplateLoader) {
var getPopup = function() {
// Make sure there is only one loading element on the page at one point in time

View File

@@ -1,6 +1,6 @@
angular.module('ionic.service.templateLoad', [])
.factory('TemplateLoader', ['$q', '$http', '$templateCache', function($q, $http, $templateCache) {
.factory('$ionicTemplateLoader', ['$q', '$http', '$templateCache', function($q, $http, $templateCache) {
return {
load: function(url) {
var deferred = $q.defer();

View File

@@ -50,8 +50,8 @@ angular.module('ionic.service.view', ['ui.router'])
}])
.factory('ViewService', ['$rootScope', '$state', '$location', '$window', '$injector',
function( $rootScope, $state, $location, $window, $injector) {
.factory('$ionicViewService', ['$rootScope', '$state', '$location', '$window', '$injector',
function( $rootScope, $state, $location, $window, $injector) {
var $animate = $injector.has('$animate') ? $injector.get('$animate') : false;
var View = function(){};
@@ -200,17 +200,23 @@ angular.module('ionic.service.view', ['ui.router'])
hist.stack.push(viewHistory.histories[rsp.viewId]);
}
viewHistory.currentView = this._getView(rsp.viewId);
viewHistory.backView = this._getBackView(viewHistory.currentView);
viewHistory.forwardView = this._getForwardView(viewHistory.currentView);
this.setNavViews(rsp.viewId);
hist.cursor = viewHistory.currentView.index;
return rsp;
},
setNavViews: function(viewId) {
var viewHistory = $rootScope.$viewHistory;
viewHistory.currentView = this._getView(viewId);
viewHistory.backView = this._getBackView(viewHistory.currentView);
viewHistory.forwardView = this._getForwardView(viewHistory.currentView);
$rootScope.$broadcast('$viewHistory.historyChange', {
showBack: (viewHistory.backView && viewHistory.backView.historyId === viewHistory.currentView.historyId)
});
return rsp;
},
registerHistory: function(scope) {
@@ -337,6 +343,7 @@ angular.module('ionic.service.view', ['ui.router'])
if($animate && animationClass && opts.doAnimation !== false && opts.navDirection) {
// set the animation we're gonna use
this.setAnimationClass(opts.parentElement, animationClass, opts.navDirection);
opts.enteringElement.addClass('ng-enter');
// start the animations
if(opts.leavingElement) {
@@ -351,11 +358,6 @@ angular.module('ionic.service.view', ['ui.router'])
}
opts.parentElement.append(opts.enteringElement);
}
$rootScope.$broadcast('viewState.viewEnter', {
title: (opts.enteringScope ? opts.enteringScope.title : null),
navDirection: (opts.navDirection ? opts.navDirection : null)
});
function getAnimationClass(){
// go up the ancestors looking for an animation value
@@ -381,6 +383,31 @@ angular.module('ionic.service.view', ['ui.router'])
// make sure the reverse class isn't already added
element[0].classList.remove('reverse');
}
},
clearHistory: function() {
var historyId, x, view,
histories = $rootScope.$viewHistory.histories,
currentView = $rootScope.$viewHistory.currentView;
for(historyId in histories) {
if(histories[historyId].stack) {
histories[historyId].stack = [];
histories[historyId].cursor = -1;
}
if(currentView.historyId === historyId) {
currentView.backViewId = null;
currentView.forwardViewId = null;
histories[historyId].stack.push(currentView);
} else if(histories[historyId].destroy) {
histories[historyId].destroy();
}
}
this.setNavViews(currentView.viewId);
}
};

View File

@@ -139,9 +139,9 @@
<script>
angular.module('actionTest', ['ionic', 'ngAnimate'])
.controller('ActionCtrl', function($scope, ActionSheet) {
.controller('ActionCtrl', function($scope, $ionicActionSheet) {
$scope.show = function() {
ActionSheet.show({
$ionicActionSheet.show({
buttons: [
{ text: 'Share' },
{ text: 'Move' },

View File

@@ -52,6 +52,11 @@
bottom: 10px;
width: 100%;
}
#search-box {
margin-bottom: 20px;
}
.scroll {
}
</style>
</head>
@@ -60,14 +65,26 @@
<header-bar id="header" title="'Title'" type="bar-primary" hides-header></header-bar>
<content id="container"
start-y="55"
on-scroll="onScroll(event, scrollTop, scrollLeft)"
on-scroll-complete="onScrollComplete(scrollTop, scrollLeft)"
on-refresh="onRefresh()"
on-refresh-opening="onRefreshOpening(amount)"
refresh-complete="refreshComplete"
padding="true"
has-tabs="true"
has-header="true"
>
<div id="search-box" class="bar bar-header item-input-inset">
<label class="item-input-wrapper">
<i class="icon ion-ios7-search placeholder-icon"></i>
<input type="search" placeholder="Search">
</label>
<button class="button button-clear">
Cancel
</button>
</div>
<button ng-click="add()">Click</button>
<ul class="list" ng-controller="AppCtrl">
<li class="list-item" ng-repeat="item in items">asdf{{$index}}</li>
</ul>
@@ -115,6 +132,9 @@
var startTop = header.offsetTop;
$scope.onScrollComplete = function(event, scrollTop, scrollLeft) {
}
$scope.add = function() {
console.log('Adding!');
};
var last = 0;
$scope.onScroll = function(event, scrollTop, scrollLeft) {
/*

View File

@@ -0,0 +1,80 @@
<html ng-app="navTest">
<head>
<meta charset="utf-8">
<title>Content</title>
<!-- Sets initial viewport load and disables zooming -->
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no">
<link rel="stylesheet" href="../../../../dist/css/ionic.css">
<script src="../../../../dist/js/ionic.js"></script>
<script src="../../../../dist/js/angular/angular.js"></script>
<script src="../../../../dist/js/angular/angular-animate.js"></script>
<script src="../../../../dist/js/angular/angular-route.js"></script>
<script src="../../../../dist/js/angular/angular-touch.js"></script>
<script src="../../../../dist/js/angular/angular-sanitize.js"></script>
<script src="../../../../dist/js/angular-ui/angular-ui-router.js"></script>
<script src="../../../../dist/js/ionic-angular.js"></script>
<style>
.reveal-animation {
/*
-webkit-transform: translate3d(0%, 0, 0);
transform: translate3d(0%, 0, 0);
-webkit-transition: -webkit-transform 1s ease-in-out;
transition: transform 1s ease-in-out;
*/
}
.reveal-animation.ng-enter {
-webkit-transition: .2s ease-in-out all;
-webkit-transform:translate3d(100%,0,0) ;
}
.reveal-animation.ng-enter-active {
-webkit-transform:translate3d(0,0,0) ;
}
.reveal-animation.ng-leave {
-webkit-transition: .2s ease-in-out all;
-webkit-transform:translate3d(0%,0,0);
}
.reveal-animation.ng-leave-active {
-webkit-transition: .2s ease-in-out all;
-webkit-transform:translate3d(-100%,0,0);
}
.scroll-refresher {
border-bottom: 1px solid #eee;
}
#refresh-content {
color: #999;
text-align: center;
font-size: 48px;
position: absolute;
bottom: 10px;
width: 100%;
}
</style>
</head>
<body>
<tabs>
<tab ng-controller="MyCtrl">
<content>
<button ng-click="add()">add</button>
{{count}}
</content>
</tab>
</tabs>
<script>
angular.module('navTest', ['ionic'])
.controller('MyCtrl', function($scope) {
$scope.count = 0;
$scope.add = function(){
$scope.count ++;
}
});
</script>
</body>
</html>

View File

@@ -20,6 +20,14 @@ describe('Ionic Content directive', function() {
expect(element.hasClass('has-header')).toEqual(true);
});
it('should add padding classname', function() {
element = compile('<content padding="true"></content>')(scope);
expect(element.hasClass('scroll-content')).toEqual(true);
expect(element.hasClass('padding')).toEqual(false);
var scrollElement = element.find('.scroll');
expect(scrollElement.hasClass('padding')).toEqual(true);
});
/**
* Not currently possible to mock this AFAIK
*/
@@ -31,4 +39,14 @@ describe('Ionic Content directive', function() {
var scrollView = scope.scrollView;
expect(scrollView.options.bouncing).toBe(false);
});
it('Should set start x and y', function() {
element = compile('<content start-x="100" start-y="300" has-header="true"></content>')(scope);
timeout.flush();
var newScope = element.isolateScope();
var scrollView = scope.scrollView;
var vals = scrollView.getValues();
expect(vals.left).toBe(100);
expect(vals.top).toBe(300);
});
});

View File

@@ -92,7 +92,7 @@ describe('Ionic Item Directive', function () {
itemElement = $compile(itemElement)($rootScope);
$rootScope.$digest();
itemScope = itemElement.isolateScope();
expect(itemScope.itemClass).toBe("item-type-test");
expect(itemScope.itemType).toBe("item-type-test");
expect(itemElement.hasClass('item-type-test')).toBe(true);
}));
@@ -103,7 +103,6 @@ describe('Ionic Item Directive', function () {
itemElement = $compile(itemElement)($rootScope);
$rootScope.$digest();
itemScope = itemElement.isolateScope();
expect(itemScope.itemClass).toBe('list-item-type-test');
expect(itemElement.hasClass('list-item-type-test')).toBe(true);
}));

View File

@@ -1,19 +0,0 @@
describe('Angular Ionic Nav Router', function() {
var modal, q;
beforeEach(module('ngRoute'));
beforeEach(module('ionic.ui.navRouter'));
beforeEach(inject(function($compile, $rootScope, $controller) {
compile = $compile;
scope = $rootScope;
}));
it('Should init', function() {
element = compile('<pane nav-router>' +
'<nav-bar></nav-bar>' +
'<ng-view></ng-view>' +
'</pane>')(scope);
});
});

View File

@@ -3,13 +3,16 @@
* see the core Ionic sideMenu controller tests.
*/
describe('Ionic Angular Slide Box', function() {
var el, delegate, timeout;
var el, delegate, compile, rootScope, timeout;
beforeEach(module('ionic'));
beforeEach(inject(function($compile, $rootScope, $timeout, SlideBoxDelegate) {
delegate = SlideBoxDelegate;
beforeEach(inject(function($compile, $rootScope, $timeout, $ionicSlideBoxDelegate) {
delegate = $ionicSlideBoxDelegate;
timeout = $timeout;
rootScope = $rootScope;
compile = $compile;
el = $compile('<slide-box>\
<slide>\
<div class="box blue">\
@@ -40,4 +43,25 @@ describe('Ionic Angular Slide Box', function() {
timeout.flush();
expect(slideBox.setup).toHaveBeenCalled();
});
it('Should set initial active slide', function() {
el = compile('<slide-box active-slide="2">\
<slide>\
<div class="box blue">\
<h1>BLUE {{slideBox.slideIndex}}</h1>\
</div>\
</slide>\
<slide>\
<div class="box yellow">\
<h1>YELLOW {{slideBox.slideIndex}}</h1>\
</div>\
</slide>\
<slide>\
<div class="box pink"><h1>PINK {{slideBox.slideIndex}}</h1></div>\
</slide>\
</slide-box>')(rootScope);
var scope = el.scope();
expect(scope.slideBox.getPos()).toBe(2);
});
});

View File

@@ -0,0 +1,81 @@
'use strict';
describe('Ionic View', function() {
var compile, scope, listElement, listCtrl;
beforeEach(module('ionic.ui.viewState'));
beforeEach(inject(function($compile, $rootScope, $controller) {
compile = $compile;
scope = $rootScope;
}));
it('should init a view', function() {
var element = compile('<view>me view</view>')(scope);
expect(element.html()).toEqual('me view');
});
it('should add pane classname and remove title from view', function() {
var element = compile('<view title="\'Me Title\'"></view>')(scope);
expect(element.attr('title')).toBeUndefined();
expect(element.hasClass('pane')).toEqual(true);
});
it('should broacast view enter on link', function() {
spyOn(scope, '$broadcast');
var element = compile('<view title="\'Me Title\'"></view>')(scope);
expect(scope.$broadcast).toHaveBeenCalledWith('viewState.viewEnter', { title: 'Me Title', navDirection: undefined });
scope.$navDirection = 'forward';
element = compile('<view title="\'Me Title\'"></view>')(scope);
expect(scope.$broadcast).toHaveBeenCalledWith('viewState.viewEnter', { title: 'Me Title', navDirection: 'forward' });
});
it('should set hide back button', function() {
spyOn(scope, '$broadcast');
var element = compile('<view></view>')(scope);
var viewScope = element.isolateScope();
expect(viewScope.hideBackButton).toBeUndefined();
expect(scope.$broadcast).not.toHaveBeenCalledWith('viewState.showBackButton', false);
element = compile('<view hide-back-button="true"></view>')(scope);
viewScope = element.isolateScope();
expect(viewScope.hideBackButton).toEqual(true);
expect(scope.$broadcast).toHaveBeenCalledWith('viewState.showBackButton', false);
});
it('should show/hide viewBack', function() {
var element = compile('<button view-back>BUTTON</button>')(scope);
expect(element.hasClass('hide')).toEqual(true);
scope.$broadcast('viewState.showBackButton', true);
expect(element.hasClass('hide')).toEqual(false);
scope.$broadcast('$viewHistory.historyChange', { showBack: false });
expect(element.hasClass('hide')).toEqual(true);
});
it('should show/hide navBar', function() {
var element = compile('<nav-bar></nav-bar>')(scope);
expect(element.hasClass('invisible')).toEqual(true);
scope.$broadcast('viewState.showNavBar', true);
scope.$digest();
expect(element.hasClass('invisible')).toEqual(false);
scope.$broadcast('viewState.showNavBar', false);
scope.$digest();
expect(element.hasClass('invisible')).toEqual(true);
});
it('should hide navBar when using view attr', function() {
var element = compile('<div><nav-bar></nav-bar><view hide-nav-bar="true"></view></div>')(scope);
scope.$digest();
var navBar = element.find('header')
expect(navBar.hasClass('invisible')).toEqual(true);
element = compile('<div><nav-bar></nav-bar><view></view></div>')(scope);
scope.$digest();
navBar = element.find('header')
expect(navBar.hasClass('invisible')).toEqual(false);
});
});

View File

@@ -38,7 +38,7 @@
.controller('AppCtrl', function($scope, $compile, $element) {
})
.directive('box', function(Gesture) {
.directive('box', function($ionicGesture) {
return {
restrict: 'C',
link: function($scope, $element, $attr) {
@@ -58,40 +58,40 @@
var tapFn = function(e) {
o('tap', [e.gesture.touches[0].pageX, e.gesture.touches[0].pageY]);
};
var tapGesture = Gesture.on('tap', tapFn, $element);
var tapGesture = $ionicGesture.on('tap', tapFn, $element);
var releaseFn = function(e) {
o('release', [e.gesture.touches[0].pageX, e.gesture.touches[0].pageY]);
};
var releaseGesture = Gesture.on('release', releaseFn, $element);
var releaseGesture = $ionicGesture.on('release', releaseFn, $element);
var holdFn = function(e) {
o('hold', [e.gesture.touches[0].pageX, e.gesture.touches[0].pageY]);
};
var holdGesture = Gesture.on('hold', holdFn, $element);
var holdGesture = $ionicGesture.on('hold', holdFn, $element);
var dragFn = function(e) {
o('drag', [e.gesture.touches[0].pageX, e.gesture.touches[0].pageY, e.gesture.deltaX, e.gesture.deltaY]);
};
var dragGesture = Gesture.on('drag', dragFn, $element);
var dragGesture = $ionicGesture.on('drag', dragFn, $element);
var swipeFn = function(e) {
o('swipe', [e.gesture.touches[0].pageX, e.gesture.touches[0].pageY, e.gesture.direction]);
};
var swipeGesture = Gesture.on('swipe', swipeFn, $element);
var swipeGesture = $ionicGesture.on('swipe', swipeFn, $element);
var transformFn = function(e) {
o('transform', [e.gesture.touches[0].pageX, e.gesture.touches[0].pageY, e.gesture.direction]);
};
var transformGesture = Gesture.on('transform', transformFn, $element);
var transformGesture = $ionicGesture.on('transform', transformFn, $element);
$scope.$on('$destroy', function () {
Gesture.off(dragGesture, 'drag', dragFn);
Gesture.off(holdGesture, 'hold', holdFn);
Gesture.off(releaseGesture, 'release', releaseFn);
Gesture.off(swipeGesture, 'swipe', swipeFn);
Gesture.off(tapGesture, 'tap', tapFn);
Gesture.off(transformGesture, 'transform', transformFn);
$ionicGesture.off(dragGesture, 'drag', dragFn);
$ionicGesture.off(holdGesture, 'hold', holdFn);
$ionicGesture.off(releaseGesture, 'release', releaseFn);
$ionicGesture.off(swipeGesture, 'swipe', swipeFn);
$ionicGesture.off(tapGesture, 'tap', tapFn);
$ionicGesture.off(transformGesture, 'transform', transformFn);
});
}
};

View File

@@ -22,9 +22,9 @@
<script>
angular.module('ionic.example', ['ionic.service.loading'])
.controller('LoadingCtrl', function($scope, $timeout, Loading) {
.controller('LoadingCtrl', function($scope, $timeout, $ionicLoading) {
$scope.startLoading = function() {
var loading = Loading.show({
var loading = $ionicLoading.show({
width: 200,
height: 100,
animation: 'fade-in',

View File

@@ -59,7 +59,7 @@
<script>
angular.module('modalTest', ['ionic'])
.controller('AppCtrl', function($scope, Modal) {
.controller('AppCtrl', function($scope, $ionicModal) {
$scope.contacts = [
{ name: 'Gordon Freeman' },
{ name: 'Barney Calhoun' },
@@ -80,7 +80,7 @@
$scope.closeModal = function() {
$scope.modal.hide();
};
Modal.fromTemplateUrl('modal.html', function(modal) {
$ionicModal.fromTemplateUrl('modal.html', function(modal) {
$scope.modal = modal;
}, {
animation: 'slide-in-up'

View File

@@ -0,0 +1,29 @@
describe('Ionic ActionSheet Service', function() {
var sheet, timeout;
beforeEach(module('ionic.service.actionSheet'));
beforeEach(inject(function($ionicActionSheet, $timeout) {
sheet = $ionicActionSheet;
timeout = $timeout;
}));
it('Should show', function() {
var s = sheet.show();
expect(s.el.classList.contains('active')).toBe(true);
});
it('Should handle hardware back button', function() {
// Fake cordova
window.device = {};
var s = sheet.show();
timeout.flush();
ionic.trigger('backbutton', {
target: document
});
expect(s.el.classList.contains('active')).toBe(false);
});
});

View File

@@ -3,8 +3,8 @@ describe('Ionic Gesture Service', function() {
beforeEach(module('ionic.service.gesture'));
beforeEach(inject(function(Gesture) {
gesture = Gesture;
beforeEach(inject(function($ionicGesture) {
gesture = $ionicGesture;
}));
it('Should bind', function() {

View File

@@ -1,11 +1,12 @@
describe('Ionic Modal', function() {
var modal, q;
var modal, q, timeout;
beforeEach(module('ionic.service.modal'));
beforeEach(inject(function(Modal, $q, $templateCache) {
beforeEach(inject(function($ionicModal, $q, $templateCache, $timeout) {
q = $q;
modal = Modal;
modal = $ionicModal;
timeout = $timeout;
$templateCache.put('modal.html', '<div class="modal"></div>');
}));
@@ -18,7 +19,7 @@ describe('Ionic Modal', function() {
expect(modalInstance.el.classList.contains('slide-in-up')).toBe(true);
});
xit('Should show for dynamic template', function() {
it('Should show for dynamic template', function() {
var template = '<div class="modal"></div>';
var done = false;
@@ -27,11 +28,30 @@ describe('Ionic Modal', function() {
done = true;
modalInstance.show();
expect(modalInstance.el.classList.contains('modal')).toBe(true);
expect(modalInstance.el.classList.contains('active')).toBe(true);
});
timeout.flush();
waitsFor(function() {
return done;
}, "Modal should be loaded", 100);
});
it('Should close on hardware back button', function() {
var template = '<div class="modal"></div>';
var modalInstance = modal.fromTemplate(template);
modalInstance.show();
timeout.flush();
expect(modalInstance.el.classList.contains('active')).toBe(true);
ionic.trigger('backbutton', {
target: document
});
expect(modalInstance.el.classList.contains('active')).toBe(false);
});
});

View File

@@ -37,8 +37,8 @@ describe('Ionic View Service', function() {
}));
beforeEach(inject(function(ViewService, $rootScope, $window, $location) {
viewService = ViewService;
beforeEach(inject(function($ionicViewService, $rootScope, $window, $location) {
viewService = $ionicViewService;
rootScope = $rootScope;
window = $window;
window.history.go = function(val) { return val };
@@ -675,6 +675,18 @@ describe('Ionic View Service', function() {
var tab1view2Reg2 = viewService.register(tab1Container);
expect(tab1view2Reg2.navAction).toEqual('moveBack');
expect(tab1view2Reg2.viewId).toEqual(tab1view2Reg.viewId);
var currentViewId = tab1view2Reg.viewId;
expect(rootScope.$viewHistory.histories[tab1view2Reg.historyId].stack.length).toEqual(2);
backView = viewService.getBackView();
expect(backView).toBeDefined();
viewService.clearHistory();
expect(rootScope.$viewHistory.histories[tab1view2Reg.historyId].stack.length).toEqual(1);
backView = viewService.getBackView();
expect(backView).toEqual(null);
currentView = viewService.getCurrentView();
expect(currentView.viewId).toEqual(currentViewId);
}));
it('should init root viewHistory data', inject(function() {
@@ -767,12 +779,9 @@ describe('Ionic View Service', function() {
opts.leavingElement = opts.parentElement.find('leaving');
opts.enteringElement = $compile("<entering>entering</entering>")(rootScope);
spyOn(rootScope, '$broadcast');
expect(opts.parentElement.html()).toContain("leaving");
viewService.transition(opts);
expect(opts.parentElement.html()).toContain("entering");
expect(rootScope.$broadcast).toHaveBeenCalledWith('viewState.viewEnter', { title: null, navDirection: null });
}));
it('should add the animation classname', inject(function($compile) {

View File

@@ -64,7 +64,7 @@
<script>
angular.module('slideBoxTest', ['ionic'])
.controller('SlideCtrl', function($scope, $timeout, SlideBoxDelegate) {
.controller('SlideCtrl', function($scope, $timeout, $ionicSlideBoxDelegate) {
$timeout(function() {
$scope.pages = [ {
@@ -79,7 +79,7 @@
}
];
SlideBoxDelegate.update();
$ionicSlideBoxDelegate.update();
}, 100);
})

View File

@@ -94,7 +94,7 @@
<header class="bar bar-header bar-positive">
<h1 class="title">Deadlines</h1>
</header>
<content has-header="true">
<content has-header="true" padding="true">
<h1>Deadlines</h1>
</content>
</tab>
@@ -103,7 +103,7 @@
<header class="bar bar-header bar-positive">
<h1 class="title">Settings</h1>
</header>
<content has-header="true">
<content has-header="true" padding="true">
<h1>Settings</h1>
</content>
</tab>
@@ -112,7 +112,7 @@
<header class="bar bar-header bar-positive">
<h1 class="title">Settings</h1>
</header>
<content has-header="true">
<content has-header="true" padding="true">
<h1>Settings</h1>
</content>
</tab>
@@ -146,14 +146,14 @@
})
.controller('HomeCtrl', function($scope, $timeout, Modal, ActionSheet) {
.controller('HomeCtrl', function($scope, $timeout, $ionicModal, $ionicActionSheet) {
Modal.fromTemplateUrl('newTask.html', function(modal) {
$ionicModal.fromTemplateUrl('newTask.html', function(modal) {
$scope.settingsModal = modal;
});
var removeItem = function(item, button) {
ActionSheet.show({
$ionicActionSheet.show({
buttons: [],
destructiveText: 'Delete Task',
cancelText: 'Cancel',

View File

@@ -58,10 +58,16 @@
</script>
<script id="forgot-password.html" type="text/ng-template">
<view title="'Forgot Password'">
<view title="'Forgot Password'" hide-nav-bar="true">
<content has-header="true" padding="true">
<p>Seriously!? Again?!</p>
<p>How about I just give you a password, hows this: <br><code>{{password}}</code></p>
<p>This view hides the nav bar using the hideNavBar attribute.</p>
<p>
<button ng-click="hideNavBar()">Hide Nav Bar</button>
<button ng-click="showNavBar()">Show Nav Bar</button>
</p>
<p>
<button ng-click="clearViewHistory()">Clear View History</button>
</p>
<p class="text-center">
<a href="#/sign-in">Sign-In</a> -
<a href="#/forgot-password">Forgot password</a> -
@@ -77,8 +83,10 @@
</script>
<script id="contact.html" type="text/ng-template">
<view title="'Contact'">
<view hide-back-button="true">
<content has-header="true" padding="true">
<p>The views title is blank on purpose.</p>
<p>The hideBackButton attribute is "true" for this view.</p>
<p>@drifty</p>
<p class="text-center">
<a href="#/sign-in">Sign-In</a> -
@@ -176,6 +184,11 @@
<a ng-href="#/tabs/autos/6" class="ng-binding" href="#/tabs/autos/6">1948 Tucker 48</a>
</li>
</ul>
<p>
<button ng-click="hideBackButton()">Hide Back Button</button>
<button ng-click="showBackButton()">Show Back Button</button>
</p>
<p><a class="button" href="#/tabs/autos">Auto List</a></p>
<p>
Current View: {{ $viewHistory.currentView }}<br>
Back View: {{ $viewHistory.backView }}<br>
@@ -296,16 +309,23 @@
})
.controller('SignInCtrl', function($scope, $state) {
//console.log('SignInCtrl');
$scope.signIn = function(user) {
$state.go('tabs.autolist');
};
})
.controller('ForgotPasswordCtrl', function($scope, $state) {
//console.log('ForgotPasswordCtrl');
$scope.password = Math.round(Math.random() * 10000);
.controller('ForgotPasswordCtrl', function($ionicViewService, $rootScope, $scope, $state) {
$scope.clearViewHistory = function() {
$ionicViewService.clearHistory();
};
$scope.hideNavBar = function() {
$rootScope.$broadcast('viewState.showNavBar', false);
};
$scope.showNavBar = function() {
$rootScope.$broadcast('viewState.showNavBar', true);
};
})
.controller('AutoListCtrl', function($scope, $state) {
@@ -320,6 +340,13 @@
.controller('AutoDetailCtrl', function($scope, $state, $stateParams) {
$scope.autoDetailData = "AutoDetailCtrl Data";
$scope.hideBackButton = function() {
$scope.$emit('viewState.showBackButton', false);
};
$scope.showBackButton = function() {
$scope.$emit('viewState.showBackButton', true);
};
$scope.auto = $scope.autos[$stateParams.id];
})

View File

@@ -1,25 +1,34 @@
(function(ionic) {
ionic.Platform = {
detect: function() {
var platforms = [];
var domReady = function() {
// run when the DOM is ready
document.addEventListener("deviceready", deviceReady, false);
document.removeEventListener("DOMContentLoaded", domReady, false);
};
document.addEventListener("DOMContentLoaded", domReady, false);
this._checkPlatforms(platforms);
var deviceReady = function() {
// run when cordova is fully loaded
var platforms = [];
ionic.Platform._checkPlatforms(platforms);
var classify = function() {
if(!document.body) { return; }
for(var i = 0; i < platforms.length; i++) {
document.body.classList.add('platform-' + platforms[i]);
if(platforms.length) {
// only change the body class if we got platform info
var bodyClass = document.body.className;
for(var i = 0; i < platforms.length; i++) {
bodyClass += ' platform-' + platforms[i];
}
document.body.className = bodyClass;
}
document.removeEventListener("deviceready", deviceReady, false);
};
document.addEventListener( "DOMContentLoaded", function(){
classify();
});
classify();
},
_checkPlatforms: function(platforms) {
if(this.isCordova()) {
platforms.push('cordova');
@@ -33,6 +42,9 @@
if(this.isAndroid()) {
platforms.push('android');
}
// Return whether we detected anything
return (platforms.length > 0);
},
// Check if we are running in Cordova, which will have
@@ -58,7 +70,7 @@
// Check if the platform is the one detected by cordova
is: function(type) {
if(window.device) {
if(window.device && window.device.platform) {
return window.device.platform === type || window.device.platform.toLowerCase() === type;
}

View File

@@ -299,6 +299,9 @@ ionic.views.Scroll = ionic.views.View.inherit({
scrollingY: true,
scrollbarY: true,
startX: 0,
startY: 0,
/** The minimum size the scrollbars scale to while scrolling */
minScrollbarSizeX: 5,
minScrollbarSizeY: 5,
@@ -378,6 +381,9 @@ ionic.views.Scroll = ionic.views.View.inherit({
});
};
this.__scrollLeft = this.options.startX;
this.__scrollTop = this.options.startY;
// Get the render update function, initialize event handlers,
// and calculate the size of the scroll container
this.__callback = this.getRenderFn();

View File

@@ -1,7 +1,7 @@
{
"name": "ionic",
"private": false,
"version": "0.9.19",
"version": "0.9.20",
"devDependencies": {
"karma": "~0.10",
"grunt": "~0.4.1",

View File

@@ -244,8 +244,9 @@ $ios7-transition-duration: 250ms;
right: -1px;
bottom: 0;
left: -1px;
border-left: 1px solid #ddd;
width: auto;
border-right: 1px solid #ddd;
border-left: 1px solid #ddd;
}
> .ng-enter, &.ng-enter {
/* NEW content placed far RIGHT BEFORE it slides IN from the RIGHT */
@@ -268,8 +269,9 @@ $ios7-transition-duration: 250ms;
right: -1px;
bottom: 0;
left: -1px;
border-left: 1px solid #ddd;
width: auto;
border-right: 1px solid #ddd;
border-left: 1px solid #ddd;
}
> .ng-enter, &.ng-enter {
/* NEW content placed far LEFT BEFORE it slides IN from the LEFT */
@@ -400,7 +402,7 @@ $ios7-transition-duration: 250ms;
.slide-in-up {
// Start it down low
@include translate3d(0, 0%, 0);
@include translate3d(0, 0, 0);
opacity: 1;
&.ng-enter, .ng-enter {
@@ -432,7 +434,7 @@ $ios7-transition-duration: 250ms;
.slide-in-up-add {
@include animation-duration(400ms);
@include animation-timing-function($slide-in-up-function);
@include animation-fill-mode(both);
@include animation-fill-mode(forwards);
}
.slide-in-up-add-active {
@include animation-name(slideInUp);

View File

@@ -212,10 +212,18 @@
button.button-block,
button.button-full,
.button-full > button.button {
.button-full > button.button,
input.button.button-block {
width: 100%;
}
a.button {
text-decoration: none;
}
.button.disabled,
.button[disabled] {
opacity: .4;
cursor: default !important;
pointer-events: none;
}

View File

@@ -8,6 +8,10 @@
.bar-header {
height: 64px;
&.item-input-inset .item-input-wrapper {
margin-top: 19px !important;
}
> * {
margin-top: 20px;
}

View File

@@ -46,21 +46,6 @@ body, .ionic-body {
-webkit-user-drag: none;
}
.content:before,
.content:after {
// Uncollapse content margin if child elements DO have an margin
display: block;
overflow: hidden;
height: 0;
content: "\00a0"; // No-break space character
}
.content {
position: absolute;
width: 100%;
height: 100%;
}
.scroll-content {
top: 0;
right: 0;
@@ -108,6 +93,10 @@ body, .ionic-body {
position: absolute;
z-index: $z-index-scroll-bar;
}
// hide the scroll-bar during animations
.ng-animate .scroll-bar {
visibility: hidden;
}
.scroll-bar-h {
height: 3px;
left: 2px;

View File

@@ -3,7 +3,7 @@
$ionicons-font-path: "../fonts" !default;
$ionicons-font-family: "Ionicons" !default;
$ionicons-version: "1.4.0" !default;
$ionicons-version: "1.4.1" !default;
$ionicons-prefix: ion- !default;
$ionicon-var-alert: "\f101";

View File

@@ -1,113 +0,0 @@
/**
* Nav controllers and header bar animations
*/
// A transition like the iOS nav controller where the old controller
// slides out and the new one slides in. In this transition, the
// old controller slides out more slowly than the new one slides in.
/*
.content-slide-in {
&.ng-enter, > .ng-enter {
-webkit-transition: 0.5s ease-in-out all;
-webkit-transform:translate3d(100%,0,0) ;
box-shadow: -1px 0px 10px rgba(0,0,0,0.6);
}
&.ng-enter-active, > .ng-enter-active {
-webkit-transform:translate3d(0,0,0) ;
}
&.ng-leave, > .ng-leave {
-webkit-transition: 0.5s ease-in-out all;
-webkit-transform:translate3d(0%,0,0);
}
&.ng-leave-active, > .ng-leave-active {
-webkit-transform:translate3d(-10%,0,0);
opacity: 0.8;
}
}
*/
.content-slide-out {
&.ng-enter, > .ng-enter {
z-index: 1;
-webkit-transition: 0.5s ease-in-out all;
-webkit-transform:translate3d(-100%,0,0) ;
box-shadow: -1px 0px 10px rgba(0,0,0,0.6);
}
&.ng-enter-active, > .ng-enter-active {
-webkit-transform:translate3d(0,0,0) ;
}
&.ng-leave, > .ng-leave {
z-index: 0;
-webkit-transition: 0.5s ease-in-out all;
-webkit-transform:translate3d(0%,0,0);
}
&.ng-leave-active, > .ng-leave-active {
-webkit-transform:translate3d(10%,0,0);
opacity: 0.8;
}
}
.bar-title-in-add {
-webkit-transition: -webkit-transform 0.5s ease-in-out, opacity 0.5s ease-in-out;
-webkit-transform: translate3d(100%, 0, 0);
opacity: 0;
}
.bar-title-in-add-active {
//margin-left: -80px;
-webkit-transform: translate3d(0px, 0, 0);
opacity: 1;
}
.bar-title-in-remove {
}
.bar-title-in-remove-active {
}
.bar-title-out-add {
-webkit-transition: -webkit-transform 0.5s ease-in-out, opacity 0.5s ease-in-out;
}
.bar-title-out-add-active {
//margin-left: -80px;
-webkit-transform: translate3d(-100%, 0, 0);
opacity: 0;
}
.bar-title-out-remove {
}
.bar-title-out-remove-active {
}
.bar-button-in {
opacity: 0;
}
.bar-button-in-add {
-webkit-transition: -webkit-transform 0.5s ease-in-out, opacity 0.5s ease-in-out;
-webkit-transform: translate3d(50%, 0, 0);
opacity: 0;
}
.bar-button-in-active {
//margin-left: -80px;
-webkit-transform: translate3d(0px, 0, 0);
opacity: 1;
}
/**
* Tab controller animations
*/
.fade-in-out {
&.ng-enter, > .ng-enter {
opacity: 0;
-webkit-transition: opacity 0.3s ease-in-out;
}
&.ng-enter-active, > .ng-enter-active {
opacity: 1;
}
&.ng-leave, > .ng-leave {
opacity: 1;
-webkit-transition: opacity 0.3s ease-in-out;
}
&.ng-leave-active, > .ng-leave-active {
opacity: 0;
}
}

View File

@@ -1,65 +0,0 @@
/* the overall container of the toggle */
.toggle {
display: inline-block;
}
/* hide the actual checkbox */
.toggle input {
display: none;
}
.toggle .track {
/* the background of the toggle's track area */
/* also the track appearance when the toggle is "off" */
position: relative;
display: inline-block;
box-sizing: border-box;
width: $toggle-width;
height: $toggle-height;
border: solid $toggle-border-width $toggle-off-border-color;
border-radius: $toggle-border-radius;
background-color: $toggle-off-bg-color;
cursor: pointer;
transition: $toggle-transition-duration + .2s ease;
}
.toggle .handle {
/* the handle (circle) thats inside the toggle's track area */
/* also the appearance when the handle is "off" */
position: absolute;
display: block;
width: auto; /* override defaults */
height: auto; /* override defaults */
box-shadow: 0 0 2px rgba(0,0,0,.5), 0 4px 5px rgba(0,0,0,0.25);
border-radius: $toggle-handle-radius;
background-color: $toggle-handle-off-bg-color;
left: 0;
top: 0;
bottom: 0;
right: $toggle-border-radius;
transition: $toggle-transition-duration ease;
transition-property: left, right;
transition-delay: 0s, .05s;
}
.toggle :checked + .track {
/* When the toggle is "on" */
/* the track when the toggle is "on" */
border-color: $toggle-on-border-color;
background-color: #ccc;
box-shadow: inset 0 0 0 $toggle-border-radius $toggle-on-bg-color;
transition: $toggle-transition-duration ease;
/* the handle when the toggle is "on" */
.handle {
background-color: $toggle-handle-on-bg-color;
right: 0;
left: $toggle-border-radius;
-webkit-transform: none;
transition-delay: .05s, 0s;
}
}

View File

@@ -1,18 +0,0 @@
$toggle-width: 54px;
$toggle-height: 32px;
$toggle-border-width: 2px;
$toggle-border-radius: 20px;
$toggle-handle-radius: 20px;
$toggle-off-bg-color: #fff;
$toggle-off-border-color: #ddd;
$toggle-on-bg-color: #4bd863;
$toggle-on-border-color: $toggle-on-bg-color;
$toggle-handle-off-bg-color: #fff;
$toggle-handle-on-bg-color: $toggle-handle-off-bg-color;
$toggle-transition-duration: .2s;

View File

@@ -1,23 +0,0 @@
@charset "UTF-8";
/*!
* Copyright 2013 Drifty Co.
* http://drifty.com/
* Ionic - a powerful HTML5 mobile app framework.
* http://ionicframework.com/
*
*
* By @maxlynch, @helloimben, @adamdbradley <3
*
* Licensed under the MIT license. Please see LICENSE for more information.
*
*/
@import
"../../mixins",
"../../variables",
"variables",
"animations",
"toggle";

View File

@@ -421,10 +421,24 @@
<hr>
<p>
<a class="button disabled button-assertive" href="#">Disabled By ClassName</a>
<a class="button button-assertive" disabled href="#">Disabled By Attribute</a>
</p>
<hr>
<p>
<input type="submit" class="button button-block button-positive" name="op" value="input element">
<button class="button button-block button-positive">button element</button>
</p>
<p>
<a class="button button-assertive" href="index.html">Homepage</a>
</p>
<hr>
</main>
</body>

27
test/search-ios7.html Normal file
View File

@@ -0,0 +1,27 @@
<html>
<head>
<meta charset="utf-8">
<title>Search</title>
<!-- Sets initial viewport load and disables zooming -->
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no">
<link href="../dist/css/ionic.css" rel="stylesheet">
</head>
<body class="platform-ios7">
<section class="content overflow-scroll">
<header class="bar bar-header item-input-inset">
<label class="item-input-wrapper">
<i class="icon ion-search placeholder-icon"></i>
<input type="search" placeholder="Search">
</label>
<button class="button button-clear button-positive">
Cancel
</button>
</header>
</section>
</body>
</html>