diff --git a/CHANGELOG.md b/CHANGELOG.md
index a2ce62f74ea..327a7ab5f4a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,61 @@
+
+# [2.0.0-beta.9](https://github.com/driftyco/ionic/compare/v2.0.0-beta.8...v2.0.0-beta.9) (2016-06-16)
+
+
+### Features
+
+* **backButton:** register back button actions ([84f37cf](https://github.com/driftyco/ionic/commit/84f37cf))
+* **item:** add the ability to show a forward arrow on md and wp modes ([c41f24d](https://github.com/driftyco/ionic/commit/c41f24d))
+* **item:** two-way sliding of items ([c28aa53](https://github.com/driftyco/ionic/commit/c28aa53)), closes [#5073](https://github.com/driftyco/ionic/issues/5073)
+* **item-sliding:** two-way item sliding gestures ([5d873ff](https://github.com/driftyco/ionic/commit/5d873ff))
+* **modal:** background click and escape key dismiss (#6831) ([e5473b6](https://github.com/driftyco/ionic/commit/e5473b6)), closes [#6738](https://github.com/driftyco/ionic/issues/6738)
+* **navPop:** add nav pop method on the app instance ([9f293e8](https://github.com/driftyco/ionic/commit/9f293e8))
+* **popover:** background dismiss, escape dismiss ([1d78f78](https://github.com/driftyco/ionic/commit/1d78f78)), closes [#6817](https://github.com/driftyco/ionic/issues/6817)
+* **range:** range can be disabled ([ccd926b](https://github.com/driftyco/ionic/commit/ccd926b))
+* **select:** add placeholder as an input for select ([461ba11](https://github.com/driftyco/ionic/commit/461ba11)), closes [#6862](https://github.com/driftyco/ionic/issues/6862)
+* **tabs:** track tab selecting history, create previousTab() method ([d98f3c9](https://github.com/driftyco/ionic/commit/d98f3c9))
+
+### Bug Fixes
+
+* **button:** check for icon and add css after content checked ([f7b2ea2](https://github.com/driftyco/ionic/commit/f7b2ea2)), closes [#6662](https://github.com/driftyco/ionic/issues/6662)
+* **click-block:** click block is now showing on all screns. ([761a1f6](https://github.com/driftyco/ionic/commit/761a1f6))
+* **click-block:** fix for the click block logic ([9b78aeb](https://github.com/driftyco/ionic/commit/9b78aeb))
+* **datetime:** add styling for datetime with different labels ([adcd2fc](https://github.com/driftyco/ionic/commit/adcd2fc)), closes [#6764](https://github.com/driftyco/ionic/issues/6764)
+* **decorators:** change to match angular style guide ([9315c68](https://github.com/driftyco/ionic/commit/9315c68))
+* **item:** change ion-item-swiping to use .item-wrapper css instead ([31f62e7](https://github.com/driftyco/ionic/commit/31f62e7))
+* **item:** encode hex value in the detail arrow so it works on firefox ([03986d4](https://github.com/driftyco/ionic/commit/03986d4)), closes [#6830](https://github.com/driftyco/ionic/issues/6830)
+* **item:** improve open/close logic, update demos ([db9fa7e](https://github.com/driftyco/ionic/commit/db9fa7e))
+* **item:** item-options width calculated correctly ([64af0c8](https://github.com/driftyco/ionic/commit/64af0c8))
+* **item:** sliding item supports dynamic options + tests ([14d29e6](https://github.com/driftyco/ionic/commit/14d29e6)), closes [#5192](https://github.com/driftyco/ionic/issues/5192)
+* **item:** sliding item's width must be 100% ([efcdd20](https://github.com/driftyco/ionic/commit/efcdd20))
+* **menu:** push/overlay working correctly in landscape ([0c88589](https://github.com/driftyco/ionic/commit/0c88589))
+* **menu:** swiping menu distinguishes between opening and closing direction ([29791f8](https://github.com/driftyco/ionic/commit/29791f8)), closes [#5511](https://github.com/driftyco/ionic/issues/5511)
+* **Menu:** fix right overlay menu when rotating device ([07d55c5](https://github.com/driftyco/ionic/commit/07d55c5))
+* **modal:** add status bar padding to modal ([181129b](https://github.com/driftyco/ionic/commit/181129b))
+* **modal:** change modal display so you can scroll the entire height ([01bbc94](https://github.com/driftyco/ionic/commit/01bbc94)), closes [#6839](https://github.com/driftyco/ionic/issues/6839)
+* **navigation:** keep the click block up longer if the keyboard is open (#6884) ([d6b7d5d](https://github.com/driftyco/ionic/commit/d6b7d5d))
+* **popover:** allow target element to be positioned at left:0 ([ea450d4](https://github.com/driftyco/ionic/commit/ea450d4)), closes [#6896](https://github.com/driftyco/ionic/issues/6896)
+* **popover:** hide arrow if no event was passed ([8350df0](https://github.com/driftyco/ionic/commit/8350df0)), closes [#6796](https://github.com/driftyco/ionic/issues/6796)
+* **range:** bar height for ios should be 1px, add disabled for wp ([f2a9f2d](https://github.com/driftyco/ionic/commit/f2a9f2d))
+* **range:** stop sliding after releasing mouse outside the window ([9b2e934](https://github.com/driftyco/ionic/commit/9b2e934)), closes [#6802](https://github.com/driftyco/ionic/issues/6802)
+* **scrollView:** ensure scroll element exists for event listeners ([1188730](https://github.com/driftyco/ionic/commit/1188730))
+* **searchbar:** add opacity so the searchbar doesn't show when it's moved over ([b5f93f9](https://github.com/driftyco/ionic/commit/b5f93f9))
+* **searchbar:** only trigger the input event on clear if there is a value ([99fdcc0](https://github.com/driftyco/ionic/commit/99fdcc0)), closes [#6382](https://github.com/driftyco/ionic/issues/6382)
+* **searchbar:** position elements when the value changes not after content checked ([31c7e59](https://github.com/driftyco/ionic/commit/31c7e59))
+* **searchbar:** set a negative tabindex for the cancel button ([614ace4](https://github.com/driftyco/ionic/commit/614ace4))
+* **searchbar:** use the contrast color for the background in a toolbar ([b4028c6](https://github.com/driftyco/ionic/commit/b4028c6)), closes [#6379](https://github.com/driftyco/ionic/issues/6379)
+* **tabs:** reduce padding on tabs for ios ([fd9cdc7](https://github.com/driftyco/ionic/commit/fd9cdc7)), closes [#6679](https://github.com/driftyco/ionic/issues/6679)
+* **tap:** export isActivatable as a const so its transpiled correctly ([ce3da97](https://github.com/driftyco/ionic/commit/ce3da97))
+* **toast:** close toasts when two or more are open (#6814) ([8ff2476](https://github.com/driftyco/ionic/commit/8ff2476)), closes [(#6814](https://github.com/(/issues/6814)
+* **toast:** toast will now be enabled (#6904) ([c068828](https://github.com/driftyco/ionic/commit/c068828))
+* **virtualScroll:** detect changes in individual nodes ([f049521](https://github.com/driftyco/ionic/commit/f049521)), closes [#6137](https://github.com/driftyco/ionic/issues/6137)
+
+### Performance Improvements
+
+* **virtualScroll:** improve UIWebView virtual scroll ([ff1daa6](https://github.com/driftyco/ionic/commit/ff1daa6))
+
+
+
# [2.0.0-beta.8](https://github.com/driftyco/ionic/compare/v2.0.0-beta.7...v2.0.0-beta.8) (2016-06-06)
@@ -36,7 +94,7 @@ All Ionic component events have been renamed to start with `ion`. This is to pre
- `change` -> `ionChange`
- **DateTime**
- `change` -> `ionChange`
- - `cancel` -> `ionCancel`
+ - `cancel` -> `ionCancel`
- **InfiniteScroll**
- `infinite` -> `ionInfinite`
- **Menu**
@@ -88,13 +146,13 @@ All Ionic component events have been renamed to start with `ion`. This is to pre
```
npm install --save ionic-angular@2.0.0-beta.8
```
-
+
_or_ modify the following line to use `beta.8` in your `package.json` and then run `npm install`:
-
+
```
"ionic-angular": "^2.0.0-beta.8",
```
-
+
**This is the way to update Ionic to any version, more information can be found in the [docs](http://ionicframework.com/docs/v2/resources/using-npm/).**
2. Replace all instances of `@Page` with `@Component`:
@@ -179,29 +237,29 @@ All Ionic component events have been renamed to start with `ion`. This is to pre
5. Rename any uses of the lifecycle events, for example:
```
- onPageDidEnter() {
+ onPageDidEnter() {
console.log("Entered page!");
}
```
-
+
becomes
-
+
```
- ionViewDidEnter() {
+ ionViewDidEnter() {
console.log("Entered page!");
}
```
-
+
The full list of lifecycle name changes is in the [section above](https://github.com/driftyco/ionic/blob/2.0/CHANGELOG.md#ionic-lifecycle-events-renamed).
-
+
6. Rename any Ionic events, for example:
```
```
-
+
becomes
-
+
```
```
@@ -1144,6 +1202,6 @@ Enjoy!
### Breaking Changes
-The Web Animations polyfill is no longer shipped with the framework and may cause build errors.
+The Web Animations polyfill is no longer shipped with the framework and may cause build errors.
Projects will need to be [updated accordingly](https://github.com/driftyco/ionic-conference-app/commit/2ed59e6fd275c4616792c7b2e5aa9da4a20fb188).
diff --git a/package.json b/package.json
index 8aac04698fa..47841b05b4b 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"private": "true",
"name": "ionic2",
- "version": "2.0.0-beta.8",
+ "version": "2.0.0-beta.9",
"license": "MIT",
"repository": {
"type": "git",
@@ -102,4 +102,4 @@
"path": "node_modules/ionic-cz-conventional-changelog"
}
}
-}
+}
\ No newline at end of file
diff --git a/scripts/npm/README.md b/scripts/npm/README.md
index 4bfe8247943..8be85c12403 100644
--- a/scripts/npm/README.md
+++ b/scripts/npm/README.md
@@ -11,7 +11,7 @@ In the root of the package are ES5 sources in the CommonJS module format, their
Usually, the only import required by the user is `ionic-angular`, as everything from Ionic is exported by the package:
```
- import {App, Page} from 'ionic-angular';
+ import {App} from 'ionic-angular';
```
### Bundles
diff --git a/src/components/content/content.ts b/src/components/content/content.ts
index e298daa4398..da8ee2213b3 100644
--- a/src/components/content/content.ts
+++ b/src/components/content/content.ts
@@ -185,6 +185,13 @@ export class Content extends Ion {
}
};
}
+
+ /**
+ * @private
+ */
+ getScrollElement(): HTMLElement {
+ return this._scrollEle;
+ }
/**
* @private
diff --git a/src/components/icon/icon.ts b/src/components/icon/icon.ts
index 4e5684e273e..fff46fb429f 100644
--- a/src/components/icon/icon.ts
+++ b/src/components/icon/icon.ts
@@ -143,7 +143,7 @@ export class Icon {
css += this._name;
}
- if (this.mode === 'ios' && !this.isActive) {
+ if (this.mode === 'ios' && !this.isActive && css.indexOf('logo') < 0) {
css += '-outline';
}
diff --git a/src/components/input/native-input.ts b/src/components/input/native-input.ts
index 5eeb9c273c9..473de4477f9 100644
--- a/src/components/input/native-input.ts
+++ b/src/components/input/native-input.ts
@@ -31,7 +31,7 @@ export class NativeInput {
}
@HostListener('input', ['$event'])
- private _change(ev) {
+ private _change(ev: any) {
this.valueChange.emit(ev.target.value);
}
@@ -40,9 +40,9 @@ export class NativeInput {
var self = this;
self.focusChange.emit(true);
-
- function docTouchEnd(ev) {
- var tapped: HTMLElement = ev.target;
+
+ function docTouchEnd(ev: TouchEvent) {
+ var tapped = ev.target;
if (tapped && self.element()) {
if (tapped.tagName !== 'INPUT' && tapped.tagName !== 'TEXTAREA' && !tapped.classList.contains('input-cover')) {
self.element().blur();
@@ -178,7 +178,7 @@ export class NativeInput {
}
-function cloneInput(focusedInputEle, addCssClass) {
+function cloneInput(focusedInputEle: any, addCssClass: string) {
let clonedInputEle = focusedInputEle.cloneNode(true);
clonedInputEle.classList.add('cloned-input');
clonedInputEle.classList.add(addCssClass);
@@ -191,7 +191,7 @@ function cloneInput(focusedInputEle, addCssClass) {
return clonedInputEle;
}
-function removeClone(focusedInputEle, queryCssClass) {
+function removeClone(focusedInputEle: any, queryCssClass: string) {
let clonedInputEle = focusedInputEle.parentElement.querySelector('.' + queryCssClass);
if (clonedInputEle) {
clonedInputEle.parentNode.removeChild(clonedInputEle);
diff --git a/src/components/item/item-reorder-gesture.ts b/src/components/item/item-reorder-gesture.ts
new file mode 100644
index 00000000000..13d534ea12e
--- /dev/null
+++ b/src/components/item/item-reorder-gesture.ts
@@ -0,0 +1,148 @@
+import {Item} from './item';
+import {List} from '../list/list';
+import {UIEventManager} from '../../util/ui-event-manager';
+import {closest, Coordinates, pointerCoord, CSS, nativeRaf} from '../../util/dom';
+
+
+const AUTO_SCROLL_MARGIN = 60;
+const SCROLL_JUMP = 10;
+const ITEM_REORDER_ACTIVE = 'reorder-active';
+
+/**
+ * @private
+ */
+export class ItemReorderGesture {
+ private selectedItem: Item = null;
+ private offset: Coordinates;
+ private lastToIndex: number;
+ private lastYcoord: number;
+ private emptyZone: boolean;
+
+ private itemHeight: number;
+ private windowHeight: number;
+
+ private events: UIEventManager = new UIEventManager(false);
+
+ constructor(public list: List) {
+ let element = this.list.getNativeElement();
+ this.events.pointerEvents(element,
+ (ev: any) => this.onDragStart(ev),
+ (ev: any) => this.onDragMove(ev),
+ (ev: any) => this.onDragEnd(ev));
+ }
+
+ private onDragStart(ev: any): boolean {
+ let itemEle = ev.target;
+ if (itemEle.nodeName !== 'ION-REORDER') {
+ return false;
+ }
+
+ let item = itemEle['$ionComponent'];
+ if (!item) {
+ console.error('item does not contain ion component');
+ return false;
+ }
+ ev.preventDefault();
+
+ // Preparing state
+ this.offset = pointerCoord(ev);
+ this.offset.y += this.list.scrollContent(0);
+ this.selectedItem = item;
+ this.itemHeight = item.height();
+ this.lastToIndex = item.index;
+ this.windowHeight = window.innerHeight - AUTO_SCROLL_MARGIN;
+ item.setCssClass(ITEM_REORDER_ACTIVE, true);
+ return true;
+ }
+
+ private onDragMove(ev: any) {
+ if (!this.selectedItem) {
+ return;
+ }
+ ev.preventDefault();
+
+ // Get coordinate
+ var coord = pointerCoord(ev);
+
+ // Scroll if we reach the scroll margins
+ let scrollPosition = this.scroll(coord);
+
+ // Update selected item position
+ let ydiff = Math.round(coord.y - this.offset.y + scrollPosition);
+ this.selectedItem.setCssStyle(CSS.transform, `translateY(${ydiff}px)`);
+
+ // Only perform hit test if we moved at least 30px from previous position
+ if (Math.abs(coord.y - this.lastYcoord) < 30) {
+ return;
+ }
+
+ // Hit test
+ let overItem = this.itemForCoord(coord);
+ if (!overItem) {
+ this.emptyZone = true;
+ return;
+ }
+
+ // Move surrounding items if needed
+ let toIndex = overItem.index;
+ if (toIndex !== this.lastToIndex || this.emptyZone) {
+ let fromIndex = this.selectedItem.index;
+ this.lastToIndex = overItem.index;
+ this.lastYcoord = coord.y;
+ this.emptyZone = false;
+ nativeRaf(() => {
+ this.list.reorderMove(fromIndex, toIndex, this.itemHeight);
+ });
+ }
+ }
+
+ private onDragEnd(ev: any) {
+ if (!this.selectedItem) {
+ return;
+ }
+
+ nativeRaf(() => {
+ let toIndex = this.lastToIndex;
+ let fromIndex = this.selectedItem.index;
+ this.selectedItem.setCssClass(ITEM_REORDER_ACTIVE, false);
+ this.selectedItem = null;
+ this.list.reorderEmit(fromIndex, toIndex);
+ });
+ }
+
+ private itemForCoord(coord: Coordinates): Item {
+ let element = document.elementFromPoint(this.offset.x - 100, coord.y);
+ if (!element) {
+ return null;
+ }
+ element = closest(element, 'ion-item', true);
+ if (!element) {
+ return null;
+ }
+ let item = - (element)['$ionComponent'];
+ if (!item) {
+ console.error('item does not have $ionComponent');
+ return null;
+ }
+ return item;
+ }
+
+ private scroll(coord: Coordinates): number {
+ let scrollDiff = 0;
+ if (coord.y < AUTO_SCROLL_MARGIN) {
+ scrollDiff = -SCROLL_JUMP;
+ } else if (coord.y > this.windowHeight) {
+ scrollDiff = SCROLL_JUMP;
+ }
+ return this.list.scrollContent(scrollDiff);
+ }
+
+ /**
+ * @private
+ */
+ destroy() {
+ this.events.unlistenAll();
+ this.events = null;
+ this.list = null;
+ }
+}
diff --git a/src/components/item/item-reorder.scss b/src/components/item/item-reorder.scss
new file mode 100644
index 00000000000..ebf1f5dd904
--- /dev/null
+++ b/src/components/item/item-reorder.scss
@@ -0,0 +1,48 @@
+
+// Item reorder
+// --------------------------------------------------
+
+ion-reorder {
+ display: none;
+
+ flex: 1;
+ align-items: center;
+ justify-content: center;
+
+ max-width: 40px;
+ height: 100%;
+
+ font-size: 1.6em;
+
+ pointer-events: all;
+ touch-action: manipulation;
+
+ ion-icon {
+ pointer-events: none;
+ }
+}
+
+.reorder-enabled {
+
+ ion-item {
+ will-change: transform;
+ }
+
+ ion-reorder {
+ display: flex;
+ }
+}
+
+ion-item.reorder-active {
+ z-index: 4;
+
+ box-shadow: 0 0 10px rgba(0, 0, 0, .5);
+ opacity: .8;
+ transition: none;
+
+ pointer-events: none;
+
+ ion-reorder {
+ pointer-events: none;
+ }
+}
diff --git a/src/components/item/item-reorder.ts b/src/components/item/item-reorder.ts
new file mode 100644
index 00000000000..36268b8f4c7
--- /dev/null
+++ b/src/components/item/item-reorder.ts
@@ -0,0 +1,17 @@
+import {Component, ElementRef, Inject, forwardRef} from '@angular/core';
+import {Item} from './item';
+
+/**
+ * @private
+ */
+@Component({
+ selector: 'ion-reorder',
+ template: ``
+})
+export class ItemReorder {
+ constructor(
+ @Inject(forwardRef(() => Item)) item: Item,
+ elementRef: ElementRef) {
+ elementRef.nativeElement['$ionComponent'] = item;
+ }
+}
diff --git a/src/components/item/item-sliding-gesture.ts b/src/components/item/item-sliding-gesture.ts
index 025ec1ac5ab..3495ecbcc58 100644
--- a/src/components/item/item-sliding-gesture.ts
+++ b/src/components/item/item-sliding-gesture.ts
@@ -12,8 +12,8 @@ export class ItemSlidingGesture extends DragGesture {
selectedContainer: ItemSliding = null;
openContainer: ItemSliding = null;
- constructor(public list: List, public listEle: HTMLElement) {
- super(listEle, {
+ constructor(public list: List) {
+ super(list.getNativeElement(), {
direction: 'x',
threshold: DRAG_THRESHOLD
});
diff --git a/src/components/item/item-sliding.scss b/src/components/item/item-sliding.scss
index 66a6c0689b9..eb8997c0f5b 100644
--- a/src/components/item/item-sliding.scss
+++ b/src/components/item/item-sliding.scss
@@ -73,7 +73,7 @@ ion-item-sliding.active-slide {
opacity: 1;
transition: all 300ms cubic-bezier(.36, .66, .04, 1);
- pointer-events: all;
+ pointer-events: none;
}
ion-item-options {
diff --git a/src/components/item/item-sliding.ts b/src/components/item/item-sliding.ts
index 82b3c8190b1..46bf3167c4e 100644
--- a/src/components/item/item-sliding.ts
+++ b/src/components/item/item-sliding.ts
@@ -16,13 +16,40 @@ export const enum SideFlags {
}
/**
- * @private
+ * @name ItemOptions
+ * @description
+ * The option buttons for an `ion-item-sliding`. These buttons can be placed either on the left or right side.
+ * You can combind the `(ionSiwpe)` event plus the `expandable` directive to create a full swipe action for the item.
+ *
+ * @usage
+ *
+ * ```html
+ *
+ *
+ * Item 1
+ *
+ *
+ *
+ *
+ *
+ *```
*/
@Directive({
selector: 'ion-item-options',
})
export class ItemOptions {
+
+ /**
+ * @input {string} the side the option button should be on. Defaults to right
+ * If you have multiple `ion-item-options`, a side must be provided for each.
+ */
@Input() side: string;
+
+ /**
+ * @output {event} Expression to evaluate when the item has been fully swiped.
+ */
@Output() ionSwipe: EventEmitter = new EventEmitter();
constructor(private _elementRef: ElementRef, private _renderer: Renderer) {
@@ -46,6 +73,9 @@ export class ItemOptions {
}
}
+ /**
+ * @private
+ */
width() {
return this._elementRef.nativeElement.offsetWidth;
}
@@ -62,12 +92,30 @@ const enum SlidingState {
/**
* @name ItemSliding
- *
* @description
* A sliding item is a list item that can be swiped to reveal buttons. It requires
* an [Item](../Item) component as a child and a [List](../../list/List) component as
* a parent. All buttons to reveal can be placed in the `` element.
*
+ * @usage
+ * ```html
+ *
+ *
+ *
+ * Item
+ *
+ *
+ *
+ *
+ *
+
+ *
+ *
+ *
+ *
+ *
+ * ```
+ *
* ### Swipe Direction
* By default, the buttons are revealed when the sliding item is swiped from right to left,
* so the buttons are placed in the right side. But it's also possible to reveal them
@@ -83,7 +131,7 @@ const enum SlidingState {
*
*
- *
+ *
*