mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2026-03-13 10:22:08 +08:00
Merge branch 'list-border-refactor'
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
<ion-view>
|
||||
<background-cycler class="bg-fade" [image]="activeBgImage"></background-cycler>
|
||||
|
||||
<ion-toolbar id="header" class="no-border"><ion-title><span class="city"><i id="city-nav-icon" class="icon ion-navigate"></i> {{currentLocationString}}</span><br><current-time localtz="current.local_tz_short"></current-time></ion-title><button (click)="showSettings()" class="toolbar-secondary-item"><i class="icon ion-ios-gear"></i></button></ion-toolbar>
|
||||
<ion-toolbar id="header"><ion-title><span class="city"><i id="city-nav-icon" class="icon ion-navigate"></i> {{currentLocationString}}</span><br><current-time localtz="current.local_tz_short"></current-time></ion-title><button (click)="showSettings()" class="toolbar-secondary-item"><i class="icon ion-ios-gear"></i></button></ion-toolbar>
|
||||
|
||||
<ion-content>
|
||||
<div id="main-content">
|
||||
|
||||
@@ -13,7 +13,7 @@ $card-ios-padding-bottom: 14px !default;
|
||||
$card-ios-padding-left: 16px !default;
|
||||
|
||||
$card-ios-padding-media-top: 10px !default;
|
||||
$card-ios-padding-media-bottom: 10px !default;
|
||||
$card-ios-padding-media-bottom: 9px !default;
|
||||
|
||||
$card-ios-background-color: $list-background-color !default;
|
||||
$card-ios-box-shadow: 0 1px 2px rgba(0,0,0,.3) !default;
|
||||
@@ -43,14 +43,18 @@ ion-card {
|
||||
.list {
|
||||
margin-bottom: 0;
|
||||
|
||||
.item {
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
ion-item-content {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.item {
|
||||
padding-right: ($card-ios-padding-right / 2);
|
||||
padding-left: ($card-ios-padding-left / 2);
|
||||
padding-right: ($card-ios-padding-right / 2);
|
||||
font-size: $item-ios-font-size;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ ion-checkbox {
|
||||
@include user-select-none();
|
||||
}
|
||||
|
||||
ion-checkbox[aria-disabled=true] {
|
||||
ion-checkbox[aria-disabled=true] .item-inner > * {
|
||||
pointer-events: none;
|
||||
opacity: 0.5;
|
||||
color: $subdued-text-color;
|
||||
|
||||
@@ -33,12 +33,14 @@ import {Form} from '../../util/form';
|
||||
'(click)': 'click($event)'
|
||||
},
|
||||
template:
|
||||
'<media-checkbox disable-activated>' +
|
||||
'<checkbox-icon></checkbox-icon>' +
|
||||
'</media-checkbox>' +
|
||||
'<ion-item-content id="{{labelId}}">' +
|
||||
'<ng-content></ng-content>' +
|
||||
'</ion-item-content>'
|
||||
'<div class="item-inner">' +
|
||||
'<media-checkbox disable-activated>' +
|
||||
'<checkbox-icon></checkbox-icon>' +
|
||||
'</media-checkbox>' +
|
||||
'<ion-item-content id="{{labelId}}">' +
|
||||
'<ng-content></ng-content>' +
|
||||
'</ion-item-content>' +
|
||||
'</div>'
|
||||
})
|
||||
export class Checkbox {
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ ion-checkbox {
|
||||
|
||||
media-checkbox {
|
||||
display: block;
|
||||
margin: $item-ios-padding-media-top ($item-ios-padding-right / 2) $item-ios-padding-media-bottom ($item-ios-padding-left / 2);
|
||||
margin: $item-ios-padding-media-top $item-ios-padding-right $item-ios-padding-media-bottom 2px;
|
||||
}
|
||||
|
||||
checkbox-icon {
|
||||
|
||||
@@ -36,7 +36,8 @@ ion-checkbox {
|
||||
|
||||
media-checkbox {
|
||||
display: block;
|
||||
margin: $item-md-padding-media-top ($item-md-padding-right / 2) $item-md-padding-media-bottom ($item-md-padding-left / 2);
|
||||
// TODO convert these to sass variables
|
||||
margin: $item-md-padding-media-top 36px $item-md-padding-media-bottom 4px;
|
||||
}
|
||||
|
||||
checkbox-icon {
|
||||
|
||||
@@ -3,17 +3,19 @@
|
||||
// --------------------------------------------------
|
||||
// Icons, avatars, thumbnails, notes, etc.
|
||||
|
||||
.item > icon[small]:first-child,
|
||||
.item-inner > icon[small]:first-child {
|
||||
min-width: 18px;
|
||||
}
|
||||
|
||||
.item > icon:first-child {
|
||||
.item > icon:first-child,
|
||||
.item-inner > icon:first-child {
|
||||
min-width: 24px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.list .item > icon[small]:first-child {
|
||||
min-width: 18px;
|
||||
}
|
||||
|
||||
.item > icon {
|
||||
.item > icon,
|
||||
.item-inner > icon {
|
||||
line-height: 1;
|
||||
font-size: 2.4rem;
|
||||
|
||||
|
||||
194
ionic/components/item/item-sliding-gesture.ts
Normal file
194
ionic/components/item/item-sliding-gesture.ts
Normal file
@@ -0,0 +1,194 @@
|
||||
import {Hammer} from 'ionic/gestures/hammer';
|
||||
import {DragGesture} from 'ionic/gestures/drag-gesture';
|
||||
import {List} from '../list/list';
|
||||
|
||||
import {CSS, raf, closest} from 'ionic/util/dom';
|
||||
|
||||
|
||||
export class ItemSlidingGesture extends DragGesture {
|
||||
constructor(list: List, listEle) {
|
||||
super(listEle, {
|
||||
direction: 'x',
|
||||
threshold: 40
|
||||
});
|
||||
|
||||
this.data = {};
|
||||
this.openItems = 0;
|
||||
|
||||
this.list = list;
|
||||
this.listEle = listEle;
|
||||
this.canDrag = true;
|
||||
this.listen();
|
||||
|
||||
this.on('tap', ev => {
|
||||
if (!isFromOptionButtons(ev.target)) {
|
||||
let didClose = this.closeOpened();
|
||||
if (didClose) {
|
||||
ev.preventDefault();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this.mouseOut = (ev) => {
|
||||
this.onDragEnd(ev);
|
||||
};
|
||||
}
|
||||
|
||||
onDragStart(ev) {
|
||||
let itemContainerEle = getItemConatiner(ev.target);
|
||||
if (!itemContainerEle) return;
|
||||
|
||||
this.closeOpened(ev, itemContainerEle);
|
||||
|
||||
let openAmout = this.getOpenAmount(itemContainerEle);
|
||||
let itemData = this.get(itemContainerEle);
|
||||
|
||||
if (openAmout) {
|
||||
return ev.preventDefault();
|
||||
}
|
||||
|
||||
itemContainerEle.classList.add('active-slide');
|
||||
|
||||
this.set(itemContainerEle, 'offsetX', openAmout);
|
||||
this.set(itemContainerEle, 'startX', ev.center[this.direction]);
|
||||
|
||||
if (ev.srcEvent.type.indexOf('mouse') > -1) {
|
||||
ev.target.addEventListener('mouseout', this.mouseOut);
|
||||
}
|
||||
}
|
||||
|
||||
onDrag(ev) {
|
||||
let itemContainerEle = getItemConatiner(ev.target);
|
||||
if (!itemContainerEle || !isActive(itemContainerEle)) return;
|
||||
|
||||
let itemData = this.get(itemContainerEle);
|
||||
|
||||
if (!itemData.optsWidth) {
|
||||
itemData.optsWidth = getOptionsWidth(itemContainerEle);
|
||||
if (!itemData.optsWidth) return;
|
||||
}
|
||||
|
||||
let x = ev.center[this.direction];
|
||||
let delta = x - itemData.startX;
|
||||
|
||||
let newX = Math.max(0, itemData.offsetX - delta);
|
||||
|
||||
if (newX > itemData.optsWidth) {
|
||||
// Calculate the new X position, capped at the top of the buttons
|
||||
newX = -Math.min(-itemData.optsWidth, -itemData.optsWidth + (((delta + itemData.optsWidth) * 0.4)));
|
||||
}
|
||||
|
||||
this.open(itemContainerEle, newX, false);
|
||||
}
|
||||
|
||||
onDragEnd(ev) {
|
||||
let itemContainerEle = getItemConatiner(ev.target);
|
||||
if (!itemContainerEle || !isActive(itemContainerEle)) return;
|
||||
|
||||
// If we are currently dragging, we want to snap back into place
|
||||
// The final resting point X will be the width of the exposed buttons
|
||||
let itemData = this.get(itemContainerEle);
|
||||
|
||||
var restingPoint = itemData.optsWidth;
|
||||
|
||||
// Check if the drag didn't clear the buttons mid-point
|
||||
// and we aren't moving fast enough to swipe open
|
||||
|
||||
if (this.getOpenAmount(itemContainerEle) < (restingPoint / 2)) {
|
||||
|
||||
// If we are going left but too slow, or going right, go back to resting
|
||||
if (ev.direction & Hammer.DIRECTION_RIGHT) {
|
||||
// Left
|
||||
restingPoint = 0;
|
||||
|
||||
} else if (Math.abs(ev.velocityX) < 0.3) {
|
||||
// Right
|
||||
restingPoint = 0;
|
||||
}
|
||||
}
|
||||
|
||||
ev.target.removeEventListener('mouseout', this.mouseOut);
|
||||
|
||||
raf(() => {
|
||||
this.open(itemContainerEle, restingPoint, true);
|
||||
});
|
||||
}
|
||||
|
||||
closeOpened(ev, doNotCloseEle) {
|
||||
let didClose = false;
|
||||
if (this.openItems) {
|
||||
let openItemElements = this.listEle.querySelectorAll('.active-slide');
|
||||
for (let i = 0; i < openItemElements.length; i++) {
|
||||
if (openItemElements[i] !== doNotCloseEle) {
|
||||
this.open(openItemElements[i], 0, true);
|
||||
didClose = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return didClose;
|
||||
}
|
||||
|
||||
open(itemContainerEle, openAmount, animate) {
|
||||
let slidingEle = itemContainerEle.querySelector('ion-item');
|
||||
if (!slidingEle) return;
|
||||
|
||||
this.set(itemContainerEle, 'openAmount', openAmount);
|
||||
|
||||
clearTimeout(this.get(itemContainerEle).timerId);
|
||||
|
||||
if (openAmount > 0) {
|
||||
this.openItems++;
|
||||
|
||||
} else {
|
||||
let timerId = setTimeout(() => {
|
||||
if (slidingEle.style[CSS.transform] === '') {
|
||||
itemContainerEle.classList.remove('active-slide');
|
||||
this.openItems--;
|
||||
}
|
||||
}, 400);
|
||||
this.set(itemContainerEle, 'timerId', timerId);
|
||||
}
|
||||
|
||||
slidingEle.style[CSS.transform] = (openAmount === 0 ? '' : 'translate3d(' + -openAmount + 'px,0,0)');
|
||||
slidingEle.style[CSS.transition] = (animate ? '' : 'none');
|
||||
}
|
||||
|
||||
getOpenAmount(itemContainerEle) {
|
||||
return this.get(itemContainerEle).openAmount || 0;
|
||||
}
|
||||
|
||||
get(itemContainerEle) {
|
||||
return this.data[itemContainerEle && itemContainerEle.$ionSlide] || {};
|
||||
}
|
||||
|
||||
set(itemContainerEle, key, value) {
|
||||
if (!this.data[itemContainerEle.$ionSlide]) {
|
||||
this.data[itemContainerEle.$ionSlide] = {};
|
||||
}
|
||||
this.data[itemContainerEle.$ionSlide][key] = value;
|
||||
}
|
||||
|
||||
unlisten() {
|
||||
super.unlisten();
|
||||
this.listEle = null;
|
||||
}
|
||||
}
|
||||
|
||||
function getItemConatiner(ele) {
|
||||
return closest(ele, 'ion-item-sliding', true);
|
||||
}
|
||||
|
||||
function isFromOptionButtons(ele) {
|
||||
return !!closest(ele, 'ion-item-options', true);
|
||||
}
|
||||
|
||||
function getOptionsWidth(itemContainerEle) {
|
||||
let optsEle = itemContainerEle.querySelector('ion-item-options');
|
||||
if (optsEle) {
|
||||
return optsEle.offsetWidth;
|
||||
}
|
||||
}
|
||||
|
||||
function isActive(itemContainerEle) {
|
||||
return itemContainerEle.classList.contains('active-slide');
|
||||
}
|
||||
36
ionic/components/item/item-sliding.scss
Normal file
36
ionic/components/item/item-sliding.scss
Normal file
@@ -0,0 +1,36 @@
|
||||
|
||||
/**
|
||||
* The hidden right-side buttons that can be exposed under a list item
|
||||
* with dragging.
|
||||
*/
|
||||
|
||||
ion-item-sliding {
|
||||
display: block;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
|
||||
.item {
|
||||
position: static;
|
||||
}
|
||||
}
|
||||
|
||||
ion-item-options {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
z-index: $z-index-item-options;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
ion-item-sliding.active-slide {
|
||||
|
||||
.item {
|
||||
position: relative;
|
||||
z-index: $z-index-item-options + 1;
|
||||
}
|
||||
|
||||
ion-item-options {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
@@ -1,31 +1,7 @@
|
||||
import {Component, Directive, ElementRef, NgIf, Host, Optional, Renderer, NgZone} from 'angular2/angular2';
|
||||
import {Component, ElementRef, Optional} from 'angular2/angular2';
|
||||
|
||||
import {Gesture} from 'ionic/gestures/gesture';
|
||||
import {DragGesture} from 'ionic/gestures/drag-gesture';
|
||||
import {Hammer} from 'ionic/gestures/hammer';
|
||||
import {List} from 'ionic/components/list/list';
|
||||
import {List} from '../list/list';
|
||||
|
||||
import * as util from 'ionic/util';
|
||||
|
||||
import {CSS, raf} from 'ionic/util/dom';
|
||||
|
||||
|
||||
|
||||
@Directive({
|
||||
selector: 'ion-item-options > button,ion-item-options > [button]',
|
||||
host: {
|
||||
'(click)': 'clicked($event)'
|
||||
}
|
||||
})
|
||||
export class ItemSlidingOptionButton {
|
||||
constructor(elementRef: ElementRef) {
|
||||
}
|
||||
clicked(event) {
|
||||
// Don't allow the click to propagate
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @name ionItem
|
||||
@@ -36,238 +12,35 @@ export class ItemSlidingOptionButton {
|
||||
* @usage
|
||||
* ```html
|
||||
* <ion-list>
|
||||
* <ion-item-sliding *ng-for="#item of items" (click)="itemTapped($event, item)">
|
||||
* {{item.title}}
|
||||
* <div class="item-note" item-right>
|
||||
* {{item.note}}
|
||||
* </div>
|
||||
* <ion-item-sliding *ng-for="#item of items">
|
||||
* <ion-item (click)="itemTapped(item)">
|
||||
* {{item.title}}
|
||||
* </ion-item>
|
||||
* <ion-item-options>
|
||||
* <button (click)="favorite(item)">Favorite</button>
|
||||
* <button (click)="share(item)">Share</button>
|
||||
* </ion-item-options>
|
||||
* </ion-item>
|
||||
* </ion-list>
|
||||
* ```
|
||||
* ```
|
||||
*/
|
||||
@Component({
|
||||
selector: 'ion-item-sliding',
|
||||
inputs: [
|
||||
'sliding'
|
||||
],
|
||||
template:
|
||||
'<ng-content select="ion-item-options"></ng-content>' +
|
||||
'<ion-item-sliding-content>' +
|
||||
'<ng-content select="[item-left]"></ng-content>' +
|
||||
'<ng-content select="[item-right]"></ng-content>' +
|
||||
'<ion-item-content>' +
|
||||
'<ng-content></ng-content>'+
|
||||
'</ion-item-content>' +
|
||||
'</ion-item-sliding-content>'
|
||||
'<ng-content select="ion-item"></ng-content>' +
|
||||
'<ng-content select="ion-item-options"></ng-content>'
|
||||
})
|
||||
export class ItemSliding {
|
||||
/**
|
||||
* TODO
|
||||
* @param {ElementRef} elementRef A reference to the component's DOM element.
|
||||
*/
|
||||
constructor(elementRef: ElementRef, renderer: Renderer, @Optional() @Host() list: List, zone: NgZone) {
|
||||
this._zone = zone;
|
||||
renderer.setElementClass(elementRef, 'item', true);
|
||||
renderer.setElementAttribute(elementRef, 'tappable', '');
|
||||
|
||||
this._isOpen = false;
|
||||
this._isSlideActive = false;
|
||||
this._isTransitioning = false;
|
||||
this._transform = '';
|
||||
|
||||
this.list = list;
|
||||
|
||||
this.elementRef = elementRef;
|
||||
this.swipeButtons = {};
|
||||
this.optionButtons = {};
|
||||
constructor(@Optional() private list: List, elementRef: ElementRef) {
|
||||
list.enableSlidingItems(true);
|
||||
elementRef.nativeElement.$ionSlide = ++slideIds;
|
||||
}
|
||||
|
||||
onInit() {
|
||||
let ele = this.elementRef.nativeElement;
|
||||
this.itemSlidingContent = ele.querySelector('ion-item-sliding-content');
|
||||
this.itemOptions = ele.querySelector('ion-item-options');
|
||||
this.openAmount = 0;
|
||||
this._zone.runOutsideAngular(() => {
|
||||
this.gesture = new ItemSlideGesture(this, this.itemSlidingContent, this._zone);
|
||||
});
|
||||
close() {
|
||||
this.list.closeSlidingItems();
|
||||
}
|
||||
|
||||
onDestroy() {
|
||||
this.gesture && this.gesture.unlisten();
|
||||
this.itemSlidingContent = this.itemOptionsContent = null;
|
||||
}
|
||||
|
||||
close(andStopDrag) {
|
||||
this.openAmount = 0;
|
||||
|
||||
// Enable it once, it'll get disabled on the next drag
|
||||
raf(() => {
|
||||
this.enableAnimation();
|
||||
if (this.itemSlidingContent) {
|
||||
this.itemSlidingContent.style[CSS.transform] = 'translateX(0)';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
open(amt) {
|
||||
let el = this.itemSlidingContent;
|
||||
this.openAmount = amt || 0;
|
||||
|
||||
if (this.list) {
|
||||
this.list.setOpenItem(this);
|
||||
}
|
||||
|
||||
if (amt === '') {
|
||||
el.style[CSS.transform] = '';
|
||||
} else {
|
||||
el.style[CSS.transform] = 'translateX(' + -amt + 'px)';
|
||||
}
|
||||
}
|
||||
|
||||
isOpen() {
|
||||
return this.openAmount > 0;
|
||||
}
|
||||
|
||||
getOpenAmt() {
|
||||
return this.openAmount;
|
||||
}
|
||||
|
||||
disableAnimation() {
|
||||
this.itemSlidingContent.style[CSS.transition] = 'none';
|
||||
}
|
||||
|
||||
enableAnimation() {
|
||||
// Clear the explicit transition, allow for CSS one to take over
|
||||
this.itemSlidingContent.style[CSS.transition] = '';
|
||||
}
|
||||
|
||||
/**
|
||||
* User did a touchstart
|
||||
*/
|
||||
didTouch() {
|
||||
if (this.isOpen()) {
|
||||
this.close();
|
||||
this.didClose = true;
|
||||
|
||||
} else {
|
||||
let openItem = this.list.getOpenItem();
|
||||
if (openItem && openItem !== this) {
|
||||
this.didClose = true;
|
||||
}
|
||||
if (this.list) {
|
||||
this.list.closeOpenItem();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
class ItemSlideGesture extends DragGesture {
|
||||
constructor(item: ItemSliding, el: Element, zone) {
|
||||
super(el, {
|
||||
direction: 'x',
|
||||
threshold: el.offsetWidth
|
||||
});
|
||||
|
||||
this.item = item;
|
||||
this.canDrag = true;
|
||||
this.listen();
|
||||
|
||||
zone.runOutsideAngular(() => {
|
||||
let touchStart = (e) => {
|
||||
this.item.didTouch();
|
||||
raf(() => {
|
||||
this.item.itemOptionsWidth = this.item.itemOptions && this.item.itemOptions.offsetWidth || 0;
|
||||
})
|
||||
};
|
||||
el.addEventListener('touchstart', touchStart);
|
||||
el.addEventListener('mousedown', touchStart);
|
||||
|
||||
let touchEnd = (e) => {
|
||||
// If we have a touch end and the item is closing,
|
||||
// prevent default to stop a click from triggering
|
||||
if(this.item.didClose) {
|
||||
e.preventDefault();
|
||||
}
|
||||
this.item.didClose = false;
|
||||
};
|
||||
el.addEventListener('touchend', touchEnd);
|
||||
el.addEventListener('mouseup', touchEnd);
|
||||
el.addEventListener('mouseout', touchEnd);
|
||||
el.addEventListener('mouseleave', touchEnd);
|
||||
el.addEventListener('touchcancel', touchEnd);
|
||||
});
|
||||
}
|
||||
|
||||
onDragStart(ev) {
|
||||
if (this.item.didClose) { return; }
|
||||
|
||||
if (!this.item.itemOptionsWidth) { return; }
|
||||
|
||||
this.slide = {};
|
||||
|
||||
this.slide.offsetX = this.item.getOpenAmt();
|
||||
this.slide.startX = ev.center[this.direction];
|
||||
this.slide.started = true;
|
||||
|
||||
this.item.disableAnimation();
|
||||
}
|
||||
|
||||
onDrag(ev) {
|
||||
if (!this.slide || !this.slide.started) return;
|
||||
|
||||
this.slide.x = ev.center[this.direction];
|
||||
this.slide.delta = this.slide.x - this.slide.startX;
|
||||
|
||||
let newX = Math.max(0, this.slide.offsetX - this.slide.delta);
|
||||
|
||||
let buttonsWidth = this.item.itemOptionsWidth;
|
||||
|
||||
if (newX > this.item.itemOptionsWidth) {
|
||||
// Calculate the new X position, capped at the top of the buttons
|
||||
newX = -Math.min(-buttonsWidth, -buttonsWidth + (((this.slide.delta + buttonsWidth) * 0.4)));
|
||||
}
|
||||
|
||||
this.item.open(newX);
|
||||
}
|
||||
|
||||
onDragEnd(ev) {
|
||||
if (!this.slide || !this.slide.started) return;
|
||||
|
||||
let buttonsWidth = this.item.itemOptionsWidth;
|
||||
|
||||
// If we are currently dragging, we want to snap back into place
|
||||
// The final resting point X will be the width of the exposed buttons
|
||||
var restingPoint = this.item.itemOptionsWidth;
|
||||
|
||||
// Check if the drag didn't clear the buttons mid-point
|
||||
// and we aren't moving fast enough to swipe open
|
||||
if (this.item.openAmount < (buttonsWidth / 2)) {
|
||||
|
||||
// If we are going left but too slow, or going right, go back to resting
|
||||
if (ev.direction & Hammer.DIRECTION_RIGHT) {
|
||||
// Left
|
||||
restingPoint = 0;
|
||||
} else if (Math.abs(ev.velocityX) < 0.3) {
|
||||
// Right
|
||||
restingPoint = 0;
|
||||
}
|
||||
}
|
||||
|
||||
raf(() => {
|
||||
if (restingPoint === 0) {
|
||||
// Reset to zero
|
||||
this.item.open('');
|
||||
var buttons = this.item.itemOptions;
|
||||
clearTimeout(this.hideButtonsTimeout);
|
||||
this.hideButtonsTimeout = setTimeout(() => {
|
||||
buttons && buttons.classList.add('invisible');
|
||||
}, 250);
|
||||
|
||||
} else {
|
||||
this.item.open(restingPoint);
|
||||
}
|
||||
this.item.enableAnimation();
|
||||
|
||||
this.slide = null;
|
||||
});
|
||||
}
|
||||
}
|
||||
let slideIds = 0;
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
|
||||
|
||||
.item {
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
@@ -19,6 +18,22 @@
|
||||
|
||||
background-color: $list-background-color;
|
||||
color: $list-text-color;
|
||||
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.item-inner {
|
||||
display: flex;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
|
||||
flex: 1;
|
||||
flex-direction: inherit;
|
||||
align-items: inherit;
|
||||
align-self: stretch;
|
||||
}
|
||||
|
||||
.item-group {
|
||||
@@ -31,7 +46,7 @@
|
||||
font-weight: 500;
|
||||
width: 100%;
|
||||
z-index: 1000;
|
||||
|
||||
|
||||
&.sticky {
|
||||
position: -webkit-sticky;
|
||||
position: sticky;
|
||||
@@ -74,10 +89,6 @@ ion-item-content {
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
.list .item {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.item {
|
||||
|
||||
h1 {
|
||||
@@ -129,24 +140,6 @@ ion-input.item {
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
/**
|
||||
* The hidden right-side buttons that can be exposed under a list item
|
||||
* with dragging.
|
||||
*/
|
||||
ion-item-sliding-content {
|
||||
display: block;
|
||||
z-index: $z-index-item-options + 1;
|
||||
flex: 1;
|
||||
}
|
||||
ion-item-options {
|
||||
display: flex;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
z-index: $z-index-item-options;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
|
||||
// TEMP hack for https://github.com/angular/angular/issues/4582
|
||||
[item-right] {
|
||||
|
||||
@@ -32,10 +32,12 @@ import {Component} from 'angular2/angular2';
|
||||
selector: 'ion-item,[ion-item]',
|
||||
template:
|
||||
'<ng-content select="[item-left]"></ng-content>' +
|
||||
'<ng-content select="[item-right]"></ng-content>' +
|
||||
'<ion-item-content>' +
|
||||
'<ng-content></ng-content>'+
|
||||
'</ion-item-content>',
|
||||
'<div class="item-inner">' +
|
||||
'<ng-content select="[item-right]"></ng-content>' +
|
||||
'<ion-item-content>' +
|
||||
'<ng-content></ng-content>'+
|
||||
'</ion-item-content>' +
|
||||
'</div>',
|
||||
host: {
|
||||
'[class.item]': 'isItem'
|
||||
}
|
||||
|
||||
@@ -6,16 +6,16 @@ $item-ios-border-color: $list-border-color !default;
|
||||
$item-ios-activated-background-color: #d9d9d9 !default;
|
||||
$item-ios-font-size: 1.6rem !default;
|
||||
|
||||
$item-ios-padding-top: 13px !default;
|
||||
$item-ios-padding-top: 12px !default;
|
||||
$item-ios-padding-right: 16px !default;
|
||||
$item-ios-padding-bottom: 14px !default;
|
||||
$item-ios-padding-bottom: 13px !default;
|
||||
$item-ios-padding-left: 16px !default;
|
||||
|
||||
$item-ios-padding-media-top: 10px !default;
|
||||
$item-ios-padding-media-bottom: 10px !default;
|
||||
|
||||
$item-ios-padding-icon-top: 10px !default;
|
||||
$item-ios-padding-icon-bottom: 10px !default;
|
||||
$item-ios-padding-icon-bottom: 9px !default;
|
||||
|
||||
$item-ios-avatar-size: 3.6rem !default;
|
||||
$item-ios-thumbnail-size: 5.6rem !default;
|
||||
@@ -40,171 +40,21 @@ ion-note {
|
||||
color: $item-ios-note-color;
|
||||
}
|
||||
|
||||
.list {
|
||||
|
||||
.item-group {
|
||||
// Make sure the first and last items don't have borders
|
||||
> .item:first-of-type:before {
|
||||
border-top: none !important;
|
||||
}
|
||||
> .item:last-of-type:after {
|
||||
border-top: none !important;
|
||||
}
|
||||
.item-group {
|
||||
ion-item-group-title {
|
||||
border-bottom: 1px solid $item-ios-border-color;
|
||||
}
|
||||
|
||||
.item {
|
||||
margin-top: -1px;
|
||||
padding-right: ($item-ios-padding-right / 2);
|
||||
padding-left: ($item-ios-padding-left / 2);
|
||||
font-size: $item-ios-font-size;
|
||||
|
||||
&:before {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
left: $item-ios-padding-left;
|
||||
border-top: 1px solid $item-ios-border-color;
|
||||
content: '';
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
&:after {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: $item-ios-padding-left;
|
||||
border-top: 1px solid $item-ios-border-color;
|
||||
content: '';
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
&:first-child:before,
|
||||
&:last-child:after {
|
||||
left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
ion-header + .item:first-of-type:before {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
&[inset] .item {
|
||||
&:before,
|
||||
&:after {
|
||||
left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
ion-item-content {
|
||||
margin: $item-ios-padding-top ($item-ios-padding-right / 2) $item-ios-padding-bottom ($item-ios-padding-left / 2);
|
||||
}
|
||||
|
||||
[item-left],
|
||||
[item-right] {
|
||||
margin: $item-ios-padding-media-top ($item-ios-padding-right / 2) $item-ios-padding-media-bottom ($item-ios-padding-left / 2);
|
||||
}
|
||||
|
||||
icon[item-left],
|
||||
icon[item-right] {
|
||||
margin-top: $item-ios-padding-icon-top;
|
||||
margin-bottom: $item-ios-padding-icon-bottom;
|
||||
}
|
||||
|
||||
button[item-left],
|
||||
button[item-right],
|
||||
[button][item-left],
|
||||
[button][item-right] {
|
||||
padding: 0 0.5em;
|
||||
font-size: 1.3rem;
|
||||
min-height: 25px;
|
||||
}
|
||||
|
||||
[item-left].icon-only,
|
||||
[item-right].icon-only,
|
||||
[item-left].icon-only icon,
|
||||
[item-right].icon-only icon,
|
||||
[item-left][clear],
|
||||
[item-right][clear] {
|
||||
padding: 0 1px;
|
||||
}
|
||||
|
||||
[item-left].icon-left icon,
|
||||
[item-right].icon-left icon {
|
||||
margin-left: 0;
|
||||
margin-bottom: 1px;
|
||||
padding-right: 0.3em;
|
||||
}
|
||||
|
||||
[item-left].icon-right icon,
|
||||
[item-right].icon-right icon {
|
||||
margin-right: 0;
|
||||
margin-bottom: 1px;
|
||||
}
|
||||
|
||||
ion-avatar {
|
||||
min-width: $item-ios-avatar-size;
|
||||
min-height: $item-ios-avatar-size;
|
||||
|
||||
img {
|
||||
max-width: $item-ios-avatar-size;
|
||||
max-height: $item-ios-avatar-size;
|
||||
border-radius: $item-ios-avatar-size / 2;
|
||||
}
|
||||
}
|
||||
|
||||
ion-thumbnail {
|
||||
min-width: $item-ios-thumbnail-size;
|
||||
min-height: $item-ios-thumbnail-size;
|
||||
|
||||
img {
|
||||
max-width: $item-ios-thumbnail-size;
|
||||
max-height: $item-ios-thumbnail-size;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ion-item-sliding.item {
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
ion-item-sliding-content {
|
||||
background-color: $item-ios-sliding-content-bg;
|
||||
padding-right: ($item-ios-padding-right / 2);
|
||||
padding-left: ($item-ios-padding-left / 2);
|
||||
display: flex;
|
||||
min-height: 42px;
|
||||
justify-content: center;
|
||||
|
||||
transition: $item-ios-sliding-transition;
|
||||
|
||||
// To allow the hairlines through
|
||||
margin-top: 1px;
|
||||
margin-bottom: 1px;
|
||||
}
|
||||
ion-item-options {
|
||||
button, [button] {
|
||||
min-height: calc(100% - 2px);
|
||||
height: calc(100% - 2px);
|
||||
margin: 1px 0 2px 0;
|
||||
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
|
||||
&:before{
|
||||
margin: 0 auto;
|
||||
}
|
||||
.item:first-child {
|
||||
.item-inner {
|
||||
border-top-width: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.item.activated,
|
||||
a.item.activated,
|
||||
button.item.activated,
|
||||
.item.activated ion-item-sliding-content {
|
||||
button.item.activated {
|
||||
background-color: $item-ios-activated-background-color;
|
||||
transition-duration: 0ms;
|
||||
}
|
||||
@@ -214,69 +64,3 @@ a.item,
|
||||
button.item {
|
||||
transition-duration: 200ms;
|
||||
}
|
||||
|
||||
.list,
|
||||
ion-card {
|
||||
button[ion-item]:not([detail-none]),
|
||||
a[ion-item]:not([detail-none]),
|
||||
[detail-push]:not(ion-item-sliding) {
|
||||
@include ios-detail-push-icon($item-ios-detail-push-color);
|
||||
background-repeat: no-repeat;
|
||||
background-position: right ($item-ios-padding-right - 2) center;
|
||||
background-size: 14px 14px;
|
||||
padding-right: 32px;
|
||||
}
|
||||
|
||||
ion-item-sliding[detail-push] {
|
||||
|
||||
ion-item-sliding-content {
|
||||
@include ios-detail-push-icon($item-ios-detail-push-color);
|
||||
background-repeat: no-repeat;
|
||||
background-position: right ($item-ios-padding-right - 2) center;
|
||||
background-size: 14px 14px;
|
||||
padding-right: 32px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.hairlines .list {
|
||||
|
||||
ion-item-options {
|
||||
button, [button] {
|
||||
min-height: calc(100% - 1px);
|
||||
height: calc(100% - 1px);
|
||||
margin-top: 0.55px;
|
||||
margin-bottom: 0.55px;
|
||||
}
|
||||
}
|
||||
|
||||
ion-item-sliding-content {
|
||||
margin-top: 0.55px;
|
||||
margin-bottom: 0.55px;
|
||||
}
|
||||
|
||||
.item {
|
||||
margin-top: -0.55px;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: -0.55px;
|
||||
}
|
||||
|
||||
&:before,
|
||||
&:after {
|
||||
border-top-width: 0.55px;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.item[no-lines] {
|
||||
&:before,
|
||||
&:after {
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
+ .item:before {
|
||||
border-width: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,230 +42,19 @@ ion-note {
|
||||
color: $item-md-note-color;
|
||||
}
|
||||
|
||||
.list {
|
||||
.item-group {
|
||||
// Make sure the first and last items don't have borders
|
||||
> .item:first-of-type:before {
|
||||
border-top: none !important;
|
||||
}
|
||||
> .item:last-of-type:after {
|
||||
border-top: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
.item {
|
||||
margin-top: -1px;
|
||||
padding-right: ($item-md-padding-right / 2);
|
||||
padding-left: ($item-md-padding-left / 2);
|
||||
font-size: $item-md-font-size;
|
||||
text-transform: none;
|
||||
|
||||
&:before {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
left: $item-md-padding-left;
|
||||
border-top: 1px solid $item-md-border-color;
|
||||
content: '';
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
&:after {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: $item-md-padding-left;
|
||||
border-top: 1px solid $item-md-border-color;
|
||||
content: '';
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
&:first-child:before,
|
||||
&:last-child:after {
|
||||
left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
ion-header + .item:before {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
ion-item-content {
|
||||
margin: $item-md-padding-top ($item-md-padding-right / 2) $item-md-padding-bottom ($item-md-padding-left / 2);
|
||||
}
|
||||
|
||||
[item-left],
|
||||
[item-right] {
|
||||
margin: $item-md-padding-media-top ($item-md-padding-right / 2) $item-md-padding-media-bottom ($item-md-padding-left / 2);
|
||||
}
|
||||
|
||||
icon[item-left],
|
||||
icon[item-right] {
|
||||
margin-top: $item-md-padding-icon-top;
|
||||
margin-bottom: $item-md-padding-icon-bottom;
|
||||
}
|
||||
|
||||
button[item-left],
|
||||
button[item-right],
|
||||
[button][item-left],
|
||||
[button][item-right] {
|
||||
padding: 0 0.6em;
|
||||
min-height: 26px;
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
[item-left].icon-only,
|
||||
[item-right].icon-only,
|
||||
[item-left].icon-only icon,
|
||||
[item-right].icon-only icon {
|
||||
padding: 0 1px;
|
||||
}
|
||||
|
||||
[item-left][clear],
|
||||
[item-right][clear] {
|
||||
padding: 0 8px;
|
||||
}
|
||||
|
||||
[item-left].icon-left icon,
|
||||
[item-right].icon-left icon {
|
||||
margin-left: 0;
|
||||
margin-bottom: 1px;
|
||||
padding-right: 0.3em;
|
||||
}
|
||||
|
||||
[item-left].icon-right icon,
|
||||
[item-right].icon-right icon {
|
||||
margin-right: 0;
|
||||
margin-bottom: 1px;
|
||||
}
|
||||
|
||||
[text-wrap] ion-item-content {
|
||||
font-size: $item-md-body-text-font-size;
|
||||
line-height: $item-md-body-text-line-height;
|
||||
}
|
||||
|
||||
.item[actions] ion-item-content {
|
||||
margin: 4px;
|
||||
}
|
||||
|
||||
icon[item-left] + ion-item-content,
|
||||
icon[item-left] + [text-input] {
|
||||
margin-left: $item-md-padding-left + ($item-md-padding-left / 2);
|
||||
}
|
||||
|
||||
ion-avatar {
|
||||
min-width: $item-md-avatar-size;
|
||||
min-height: $item-md-avatar-size;
|
||||
|
||||
img {
|
||||
max-width: $item-md-avatar-size;
|
||||
max-height: $item-md-avatar-size;
|
||||
border-radius: $item-md-avatar-size / 2;
|
||||
}
|
||||
}
|
||||
|
||||
ion-thumbnail {
|
||||
min-width: $item-md-thumbnail-size;
|
||||
min-height: $item-md-thumbnail-size;
|
||||
|
||||
img {
|
||||
max-width: $item-md-thumbnail-size;
|
||||
max-height: $item-md-thumbnail-size;
|
||||
}
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin: 0 0 2px;
|
||||
font-size: 2.4rem;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin: 2px 0 2px;
|
||||
font-size: 1.6rem;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
line-height: normal;
|
||||
margin: 2px 0 2px;
|
||||
font-size: 1.4rem;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
p {
|
||||
line-height: normal;
|
||||
color: #666;
|
||||
font-size: 1.4rem;
|
||||
margin: 0 0 2px;
|
||||
}
|
||||
|
||||
button.item.activated {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
ion-item-sliding.item {
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
ion-item-sliding-content {
|
||||
background-color: $item-md-sliding-content-bg;
|
||||
padding-right: ($item-md-padding-right / 2);
|
||||
padding-left: ($item-md-padding-left / 2);
|
||||
display: flex;
|
||||
min-height: 42px;
|
||||
justify-content: center;
|
||||
|
||||
transition: $item-md-sliding-transition;
|
||||
|
||||
// To allow the hairlines through
|
||||
margin-top: 1px;
|
||||
margin-bottom: 1px;
|
||||
}
|
||||
ion-item-options {
|
||||
button, [button] {
|
||||
height: calc(100% - 2px);
|
||||
margin: 1px 0 1px 0;
|
||||
box-shadow: none;
|
||||
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
|
||||
&:before{
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.item,
|
||||
a.item,
|
||||
button.item,
|
||||
.item ion-item-sliding-content {
|
||||
transition: background-color $button-md-transition-duration $button-md-animation-curve;
|
||||
button.item {
|
||||
transition: background-color $button-md-transition-duration $button-md-animation-curve, transform 300ms;
|
||||
}
|
||||
|
||||
.item.activated,
|
||||
a.item.activated,
|
||||
button.item.activated,
|
||||
.item.activated ion-item-sliding-content {
|
||||
button.item.activated {
|
||||
background-color: $item-md-activated-background-color;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.item[no-lines] {
|
||||
&:before,
|
||||
&:after {
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
+ .item:before {
|
||||
border-width: 0;
|
||||
}
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
@@ -1,29 +1,35 @@
|
||||
import {App} from 'ionic/ionic';
|
||||
import {App, IonicApp} from 'ionic/ionic';
|
||||
|
||||
|
||||
@App({
|
||||
templateUrl: 'main.html'
|
||||
})
|
||||
class E2EApp {
|
||||
constructor() {
|
||||
constructor(private app: IonicApp) {
|
||||
setTimeout(() => {
|
||||
this.shouldShow = true;
|
||||
}, 10);
|
||||
}
|
||||
|
||||
closeOpened() {
|
||||
this.app.getComponent('myList').closeSlidingItems();
|
||||
}
|
||||
|
||||
getItems() {
|
||||
console.log('getItems');
|
||||
return [0,1];
|
||||
}
|
||||
|
||||
didClick(e) {
|
||||
console.log('CLICK', e.defaultPrevented, e)
|
||||
didClick(ev, item) {
|
||||
console.log('CLICK', ev.defaultPrevented, ev)
|
||||
}
|
||||
|
||||
archive(e) {
|
||||
console.log('Accept', e);
|
||||
archive(ev, item) {
|
||||
console.log('Archive', ev, item);
|
||||
item.close();
|
||||
}
|
||||
del(e) {
|
||||
console.log('Delete', e);
|
||||
|
||||
del(ev, item) {
|
||||
console.log('Delete', ev, item);
|
||||
item.close();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,77 +1,99 @@
|
||||
<ion-toolbar><ion-title>Sliding Items</ion-title></ion-toolbar>
|
||||
|
||||
<ion-list>
|
||||
<ion-content>
|
||||
|
||||
<ion-list id="myList">
|
||||
|
||||
<ion-item-sliding text-wrap detail-push (click)="didClick($event)">
|
||||
<h3>Max Lynch</h3>
|
||||
<p>
|
||||
Hey do you want to go to the game tonight?
|
||||
</p>
|
||||
<ion-item-options>
|
||||
<button primary (click)="archive($event)">Archive</button>
|
||||
<button danger (click)="del($event)">Delete</button>
|
||||
</ion-item-options>
|
||||
</ion-item-sliding>
|
||||
<ion-item-sliding #item>
|
||||
<ion-item text-wrap detail-push (click)="didClick($event, item)">
|
||||
<h3>Max Lynch</h3>
|
||||
<p>
|
||||
Hey do you want to go to the game tonight?
|
||||
</p>
|
||||
</ion-item>
|
||||
<ion-item-options>
|
||||
<button primary (click)="archive($event, item)">Archive</button>
|
||||
<button danger (click)="del($event, item)">Delete</button>
|
||||
</ion-item-options>
|
||||
</ion-item-sliding>
|
||||
|
||||
<ion-item-sliding text-wrap detail-push class="activated">
|
||||
<h3>Adam Bradley</h3>
|
||||
<p>
|
||||
I think I figured out how to get more Mountain Dew
|
||||
</p>
|
||||
<ion-item-options>
|
||||
<button primary>Archive</button>
|
||||
<button danger><icon trash></icon></button>
|
||||
</ion-item-options>
|
||||
</ion-item-sliding>
|
||||
<ion-item-sliding #item>
|
||||
<ion-item text-wrap detail-push class="activated">
|
||||
<h3>Adam Bradley</h3>
|
||||
<p>
|
||||
I think I figured out how to get more Mountain Dew
|
||||
</p>
|
||||
</ion-item>
|
||||
<ion-item-options>
|
||||
<button primary (click)="archive($event, item)">Archive</button>
|
||||
<button danger (click)="del($event, item)"><icon trash></icon></button>
|
||||
</ion-item-options>
|
||||
</ion-item-sliding>
|
||||
|
||||
<ion-item-sliding text-wrap detail-push *ng-if="shouldShow">
|
||||
<h3>Ben Sperry</h3>
|
||||
<p>
|
||||
I like paper
|
||||
</p>
|
||||
<ion-item-options>
|
||||
<button primary>Archive</button>
|
||||
<button danger>Delete</button>
|
||||
</ion-item-options>
|
||||
</ion-item-sliding>
|
||||
<ion-item-sliding text-wrap detail-push *ng-if="shouldShow" #item>
|
||||
<ion-item>
|
||||
<h3>Ben Sperry</h3>
|
||||
<p>
|
||||
I like paper
|
||||
</p>
|
||||
</ion-item>
|
||||
<ion-item-options>
|
||||
<button primary (click)="archive($event, item)">Archive</button>
|
||||
<button danger (click)="del($event, item)">Delete</button>
|
||||
</ion-item-options>
|
||||
</ion-item-sliding>
|
||||
|
||||
<ion-item-sliding>
|
||||
<icon mail item-left></icon>
|
||||
One Line w/ Icon, div only text
|
||||
<ion-item-options>
|
||||
<button primary>Archive</button>
|
||||
</ion-item-options>
|
||||
</ion-item-sliding>
|
||||
<ion-item-sliding #item>
|
||||
<ion-item>
|
||||
<icon mail item-left></icon>
|
||||
One Line w/ Icon, div only text
|
||||
</ion-item>
|
||||
<ion-item-options>
|
||||
<button primary (click)="archive($event, item)">Archive</button>
|
||||
</ion-item-options>
|
||||
</ion-item-sliding>
|
||||
|
||||
<ion-item-sliding>
|
||||
<ion-avatar item-left>
|
||||
<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAAAAACH5BAAAAAAALAAAAAABAAEAAAICTAEAOw==">
|
||||
</ion-avatar>
|
||||
One Line w/ Avatar, div only text
|
||||
<ion-item-options>
|
||||
<button primary>Archive</button>
|
||||
</ion-item-options>
|
||||
</ion-item-sliding>
|
||||
<ion-item-sliding #item>
|
||||
<ion-item>
|
||||
<ion-avatar item-left>
|
||||
<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAAAAACH5BAAAAAAALAAAAAABAAEAAAICTAEAOw==">
|
||||
</ion-avatar>
|
||||
One Line w/ Avatar, div only text
|
||||
</ion-item>
|
||||
<ion-item-options>
|
||||
<button primary (click)="archive($event, item)">Archive</button>
|
||||
</ion-item-options>
|
||||
</ion-item-sliding>
|
||||
|
||||
<ion-item-sliding>
|
||||
<ion-thumbnail item-left>
|
||||
<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAAAAACH5BAAAAAAALAAAAAABAAEAAAICTAEAOw==">
|
||||
</ion-thumbnail>
|
||||
<h2>Two Lines w/ Thumbnail, H2 Header</h2>
|
||||
<p>Paragraph text.</p>
|
||||
<ion-item-options>
|
||||
<button primary>Archive</button>
|
||||
</ion-item-options>
|
||||
</ion-item-sliding>
|
||||
<ion-item-sliding #item>
|
||||
<ion-item>
|
||||
<ion-thumbnail item-left>
|
||||
<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAAAAACH5BAAAAAAALAAAAAABAAEAAAICTAEAOw==">
|
||||
</ion-thumbnail>
|
||||
<h2>Two Lines w/ Thumbnail, H2 Header</h2>
|
||||
<p>Paragraph text.</p>
|
||||
</ion-item>
|
||||
<ion-item-options>
|
||||
<button primary (click)="archive($event, item)">Archive</button>
|
||||
</ion-item-options>
|
||||
</ion-item-sliding>
|
||||
|
||||
<ion-item-sliding text-wrap detail-push *ng-for="#item of getItems()">
|
||||
<h3>ng-for {{item}}</h3>
|
||||
<ion-item-options>
|
||||
<button primary>Archive</button>
|
||||
</ion-item-options>
|
||||
</ion-item-sliding>
|
||||
<ion-item-sliding *ng-for="#item of getItems()">
|
||||
<ion-item text-wrap detail-push>
|
||||
<h3>ng-for {{item}}</h3>
|
||||
</ion-item>
|
||||
<ion-item-options>
|
||||
<button primary (click)="archive($event, item)">Archive</button>
|
||||
</ion-item-options>
|
||||
</ion-item-sliding>
|
||||
|
||||
</ion-list>
|
||||
</ion-list>
|
||||
|
||||
<p>
|
||||
<button (click)="closeOpened()">Close opened items</button>
|
||||
</p>
|
||||
|
||||
</ion-content>
|
||||
|
||||
<style>
|
||||
img {
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import {Directive, ElementRef, Renderer} from 'angular2/angular2';
|
||||
import {Directive, ElementRef, Renderer, NgZone} from 'angular2/angular2';
|
||||
|
||||
import {Ion} from '../ion';
|
||||
import {Config} from '../../config/config';
|
||||
import {ListVirtualScroll} from './virtual';
|
||||
import {ItemSlidingGesture} from '../item/item-sliding-gesture';
|
||||
import * as util from 'ionic/util';
|
||||
|
||||
/**
|
||||
@@ -30,7 +31,7 @@ export class List extends Ion {
|
||||
* @param {ElementRef} elementRef TODO
|
||||
* @param {Config} config TODO
|
||||
*/
|
||||
constructor(elementRef: ElementRef, config: Config, renderer: Renderer) {
|
||||
constructor(elementRef: ElementRef, config: Config, renderer: Renderer, private zone: NgZone) {
|
||||
super(elementRef, config);
|
||||
renderer.setElementClass(elementRef, 'list', true);
|
||||
this.ele = elementRef.nativeElement;
|
||||
@@ -48,6 +49,12 @@ export class List extends Ion {
|
||||
this._initVirtualScrolling();
|
||||
}
|
||||
}
|
||||
|
||||
onDestroy() {
|
||||
this.ele = null;
|
||||
this.slidingGesture && this.slidingGesture.unlisten();
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* TODO
|
||||
@@ -68,20 +75,32 @@ export class List extends Ion {
|
||||
this.itemTemplate = item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Keeps track of any open item (a sliding item, for example), to close it later
|
||||
*/
|
||||
setOpenItem(item) {
|
||||
this.openItem = item;
|
||||
}
|
||||
closeOpenItem() {
|
||||
if(this.openItem) {
|
||||
this.openItem.close(true);
|
||||
this.openItem = null;
|
||||
enableSlidingItems(shouldEnable) {
|
||||
this._enableSliding = shouldEnable;
|
||||
|
||||
if (this._init) {
|
||||
if (shouldEnable) {
|
||||
this.zone.runOutsideAngular(() => {
|
||||
setTimeout(() => {
|
||||
this.slidingGesture = new ItemSlidingGesture(this, this.ele);
|
||||
});
|
||||
});
|
||||
|
||||
} else {
|
||||
this.slidingGesture && this.slidingGesture.unlisten();
|
||||
}
|
||||
}
|
||||
}
|
||||
getOpenItem() {
|
||||
return this.openItem;
|
||||
|
||||
closeSlidingItems() {
|
||||
this.slidingGesture && this.slidingGesture.closeOpened();
|
||||
}
|
||||
|
||||
afterViewInit() {
|
||||
this._init = true;
|
||||
if (this._enableSliding) {
|
||||
this.enableSlidingItems(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,6 +116,4 @@ export class List extends Ion {
|
||||
'[attr.id]': 'id'
|
||||
}
|
||||
})
|
||||
export class ListHeader {
|
||||
|
||||
}
|
||||
export class ListHeader {}
|
||||
|
||||
@@ -20,8 +20,12 @@ $list-ios-header-letter-spacing: 0.1rem !default;
|
||||
$list-ios-header-color: #333 !default;
|
||||
|
||||
|
||||
/****************/
|
||||
/* DEFAULT LIST */
|
||||
/****************/
|
||||
|
||||
.list {
|
||||
margin: 0 $list-ios-margin-right $list-ios-margin-bottom $list-ios-margin-left;
|
||||
margin: -1px $list-ios-margin-right $list-ios-margin-bottom $list-ios-margin-left;
|
||||
|
||||
ion-header {
|
||||
position: relative;
|
||||
@@ -31,56 +35,246 @@ $list-ios-header-color: #333 !default;
|
||||
letter-spacing: $list-ios-header-letter-spacing;
|
||||
text-transform: uppercase;
|
||||
color: $list-ios-header-color;
|
||||
}
|
||||
|
||||
&:after {
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
border-top: 1px solid $item-ios-border-color;
|
||||
content: '';
|
||||
pointer-events: none;
|
||||
ion-header,
|
||||
ion-item-group-title , {
|
||||
border-bottom: 1px solid $item-ios-border-color;
|
||||
}
|
||||
|
||||
.item {
|
||||
border-radius: 0;
|
||||
// TODO this makes the border not show on sticky
|
||||
padding-left: $item-ios-padding-left;
|
||||
font-size: $item-ios-font-size;
|
||||
}
|
||||
|
||||
> .item:first-child {
|
||||
border-top: 1px solid $item-ios-border-color;
|
||||
}
|
||||
|
||||
> .item:last-child,
|
||||
> ion-item-sliding:last-child .item {
|
||||
border-bottom: 1px solid $item-ios-border-color;
|
||||
|
||||
.item-inner {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
|
||||
.item {
|
||||
|
||||
.item-inner {
|
||||
padding-right: ($item-ios-padding-right / 2);
|
||||
border-bottom: 1px solid $item-ios-border-color;
|
||||
}
|
||||
|
||||
ion-item-content {
|
||||
margin: $item-ios-padding-top ($item-ios-padding-right / 2) $item-ios-padding-bottom 0;
|
||||
}
|
||||
}
|
||||
|
||||
// If the item has the no-lines attribute remove the bottom border from:
|
||||
// the item itself (for last-child items)
|
||||
// the item-inner class (if it is not last)
|
||||
.item[no-lines],
|
||||
.item[no-lines] .item-inner, {
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
[item-left] {
|
||||
margin: ($item-ios-padding-top / 2) $item-ios-padding-right ($item-ios-padding-bottom / 2) 0;
|
||||
}
|
||||
|
||||
[item-right] {
|
||||
margin: ($item-ios-padding-top / 2) ($item-ios-padding-right / 2) ($item-ios-padding-bottom / 2) ($item-ios-padding-left / 2);
|
||||
}
|
||||
|
||||
// TODO clean up Sass variables
|
||||
icon[item-left],
|
||||
icon[item-right] {
|
||||
margin-top: $item-ios-padding-icon-top;
|
||||
margin-bottom: $item-ios-padding-icon-bottom;
|
||||
}
|
||||
|
||||
ion-avatar[item-left],
|
||||
ion-thumbnail[item-left] {
|
||||
margin: ($item-ios-padding-right / 2) $item-ios-padding-right ($item-ios-padding-right / 2) 0;
|
||||
}
|
||||
|
||||
ion-avatar[item-right],
|
||||
ion-thumbnail[item-right] {
|
||||
margin: ($item-ios-padding-right / 2);
|
||||
}
|
||||
|
||||
button[item-left],
|
||||
button[item-right],
|
||||
[button][item-left],
|
||||
[button][item-right] {
|
||||
padding: 0 0.5em;
|
||||
font-size: 1.3rem;
|
||||
min-height: 25px;
|
||||
margin-top: 9px;
|
||||
}
|
||||
|
||||
[item-left].icon-only,
|
||||
[item-right].icon-only,
|
||||
[item-left].icon-only icon,
|
||||
[item-right].icon-only icon,
|
||||
[item-left][clear],
|
||||
[item-right][clear] {
|
||||
padding: 0 1px;
|
||||
}
|
||||
|
||||
[item-left].icon-left icon,
|
||||
[item-right].icon-left icon {
|
||||
margin-left: 0;
|
||||
margin-bottom: 1px;
|
||||
padding-right: 0.3em;
|
||||
}
|
||||
|
||||
[item-left].icon-right icon,
|
||||
[item-right].icon-right icon {
|
||||
margin-right: 0;
|
||||
margin-bottom: 1px;
|
||||
}
|
||||
|
||||
ion-avatar {
|
||||
min-width: $item-ios-avatar-size;
|
||||
min-height: $item-ios-avatar-size;
|
||||
|
||||
img {
|
||||
max-width: $item-ios-avatar-size;
|
||||
max-height: $item-ios-avatar-size;
|
||||
border-radius: $item-ios-avatar-size / 2;
|
||||
}
|
||||
}
|
||||
|
||||
ion-thumbnail {
|
||||
min-width: $item-ios-thumbnail-size;
|
||||
min-height: $item-ios-thumbnail-size;
|
||||
|
||||
img {
|
||||
max-width: $item-ios-thumbnail-size;
|
||||
max-height: $item-ios-thumbnail-size;
|
||||
}
|
||||
}
|
||||
|
||||
ion-item-options {
|
||||
border-bottom: 1px solid $item-ios-border-color;
|
||||
|
||||
button, [button] {
|
||||
min-height: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
|
||||
&:before{
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.hairlines .list ion-header:after {
|
||||
border-top-width: 0.55px;
|
||||
.list,
|
||||
ion-card {
|
||||
button.item:not([detail-none]) .item-inner,
|
||||
a.item:not([detail-none]) .item-inner,
|
||||
.item[detail-push] .item-inner {
|
||||
@include ios-detail-push-icon($item-ios-detail-push-color);
|
||||
background-repeat: no-repeat;
|
||||
background-position: right ($item-ios-padding-right - 2) center;
|
||||
background-size: 14px 14px;
|
||||
padding-right: 32px;
|
||||
}
|
||||
}
|
||||
|
||||
.list + .list {
|
||||
margin-top: $list-ios-margin-top + $list-ios-margin-bottom;
|
||||
|
||||
ion-header {
|
||||
margin-top: -$list-ios-margin-top;
|
||||
padding-top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.list + .list ion-header {
|
||||
margin-top: -$list-ios-margin-top;
|
||||
padding-top: 0;
|
||||
&.hairlines .list {
|
||||
|
||||
ion-item-options {
|
||||
border-width: 0.55px;
|
||||
//
|
||||
// button, [button] {
|
||||
// min-height: calc(100% - 1px);
|
||||
// height: calc(100% - 1px);
|
||||
// margin-top: 0.55px;
|
||||
// margin-bottom: 0.55px;
|
||||
// }
|
||||
}
|
||||
|
||||
ion-header,
|
||||
ion-item-group-title {
|
||||
border-bottom-width: 0.55px;
|
||||
}
|
||||
|
||||
.item {
|
||||
margin-top: -0.55px;
|
||||
|
||||
.item-inner {
|
||||
border-width: 0.55px;
|
||||
}
|
||||
}
|
||||
|
||||
> .item:first-child {
|
||||
border-top-width: 0.55px;
|
||||
}
|
||||
|
||||
> .item:last-child,
|
||||
> ion-item-sliding:last-child .item {
|
||||
border-bottom-width: 0.55px;
|
||||
margin-bottom: -0.55px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**************/
|
||||
/* INSET LIST */
|
||||
/**************/
|
||||
|
||||
.list[inset] {
|
||||
margin: $list-inset-ios-margin-top $list-inset-ios-margin-right $list-inset-ios-margin-bottom $list-inset-ios-margin-left;
|
||||
border-radius: $list-inset-ios-border-radius;
|
||||
|
||||
.item:first-child {
|
||||
.item {
|
||||
margin-top: 0;
|
||||
border-top-right-radius: $list-inset-ios-border-radius;
|
||||
border-top-left-radius: $list-inset-ios-border-radius;
|
||||
border-bottom: 1px solid $item-ios-border-color;
|
||||
|
||||
&:before {
|
||||
border-top: none;
|
||||
.item-inner {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
|
||||
.item:last-child {
|
||||
> .item:first-child,
|
||||
ion-header {
|
||||
margin-top: 0;
|
||||
border-top-right-radius: $list-inset-ios-border-radius;
|
||||
border-top-left-radius: $list-inset-ios-border-radius;
|
||||
}
|
||||
|
||||
> .item:first-child {
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
> .item:last-child,
|
||||
> ion-item-sliding:last-child .item {
|
||||
margin-bottom: 0;
|
||||
border-bottom-right-radius: $list-inset-ios-border-radius;
|
||||
border-bottom-left-radius: $list-inset-ios-border-radius;
|
||||
|
||||
&:after {
|
||||
border-top: none;
|
||||
}
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,11 +282,23 @@ $list-ios-header-color: #333 !default;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
&.hairlines .list[no-lines],
|
||||
.list[no-lines] {
|
||||
ion-header:after,
|
||||
.item:before,
|
||||
.item:after {
|
||||
&.hairlines .list[inset] {
|
||||
.item {
|
||||
border-width: 0.55px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*****************/
|
||||
/* NO LINES LIST */
|
||||
/*****************/
|
||||
|
||||
.list[no-lines],
|
||||
&.hairlines .list[no-lines] {
|
||||
ion-header,
|
||||
ion-item-group-title,
|
||||
.item,
|
||||
.item .item-inner {
|
||||
border-width: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,192 @@ $list-md-header-font-size: 1.4rem !default;
|
||||
$list-md-header-color: #858585 !default;
|
||||
|
||||
|
||||
/****************/
|
||||
/* DEFAULT LIST */
|
||||
/****************/
|
||||
|
||||
.list {
|
||||
ion-header,
|
||||
ion-item-group-title , {
|
||||
border-bottom: 1px solid $item-md-border-color;
|
||||
}
|
||||
|
||||
.item {
|
||||
padding-right: ($item-md-padding-right / 2);
|
||||
padding-left: ($item-md-padding-left);
|
||||
font-size: $item-md-font-size;
|
||||
text-transform: none;
|
||||
|
||||
.item-inner {
|
||||
border-bottom: 1px solid $item-md-border-color;
|
||||
}
|
||||
}
|
||||
|
||||
> .item:first-child {
|
||||
border-top: 1px solid $item-md-border-color;
|
||||
}
|
||||
|
||||
> .item:last-child,
|
||||
> ion-item-sliding:last-child .item {
|
||||
border-bottom: 1px solid $item-md-border-color;
|
||||
|
||||
.item-inner {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
|
||||
// If the item has the no-lines attribute remove the bottom border from:
|
||||
// the item itself (for last-child items)
|
||||
// the item-inner class (if it is not last)
|
||||
.item[no-lines],
|
||||
.item[no-lines] .item-inner {
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
ion-header,
|
||||
ion-item-group-title {
|
||||
border-bottom: 1px solid $item-md-border-color;
|
||||
margin-left: 0;
|
||||
padding-left: $item-md-padding-left;
|
||||
}
|
||||
|
||||
ion-item-content {
|
||||
margin: $item-md-padding-top ($item-md-padding-right / 2) $item-md-padding-bottom 0;
|
||||
}
|
||||
|
||||
[item-left],
|
||||
[item-right] {
|
||||
margin: $item-md-padding-media-top ($item-md-padding-right / 2) $item-md-padding-media-bottom ($item-md-padding-left / 2);
|
||||
}
|
||||
|
||||
icon[item-left],
|
||||
icon[item-right] {
|
||||
margin-top: $item-md-padding-icon-top;
|
||||
margin-left: 0;
|
||||
margin-bottom: $item-md-padding-icon-bottom;
|
||||
}
|
||||
|
||||
button[item-left],
|
||||
button[item-right],
|
||||
[button][item-left],
|
||||
[button][item-right] {
|
||||
padding: 0 0.6em;
|
||||
min-height: 26px;
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
[item-left].icon-only,
|
||||
[item-right].icon-only,
|
||||
[item-left].icon-only icon,
|
||||
[item-right].icon-only icon {
|
||||
padding: 0 1px;
|
||||
}
|
||||
|
||||
[item-left][clear],
|
||||
[item-right][clear] {
|
||||
padding: 0 8px;
|
||||
}
|
||||
|
||||
[item-left].icon-left icon,
|
||||
[item-right].icon-left icon {
|
||||
margin-left: 0;
|
||||
margin-bottom: 1px;
|
||||
padding-right: 0.3em;
|
||||
}
|
||||
|
||||
[item-left].icon-right icon,
|
||||
[item-right].icon-right icon {
|
||||
margin-right: 0;
|
||||
margin-bottom: 1px;
|
||||
}
|
||||
|
||||
[text-wrap] ion-item-content {
|
||||
font-size: $item-md-body-text-font-size;
|
||||
line-height: $item-md-body-text-line-height;
|
||||
}
|
||||
|
||||
.item[actions] ion-item-content {
|
||||
margin: 4px;
|
||||
}
|
||||
|
||||
icon[item-left] + .item-inner,
|
||||
icon[item-left] + [text-input] {
|
||||
margin-left: $item-md-padding-left + ($item-md-padding-left / 2);
|
||||
}
|
||||
|
||||
ion-avatar {
|
||||
min-width: $item-md-avatar-size;
|
||||
min-height: $item-md-avatar-size;
|
||||
|
||||
img {
|
||||
max-width: $item-md-avatar-size;
|
||||
max-height: $item-md-avatar-size;
|
||||
border-radius: $item-md-avatar-size / 2;
|
||||
}
|
||||
}
|
||||
|
||||
ion-thumbnail {
|
||||
min-width: $item-md-thumbnail-size;
|
||||
min-height: $item-md-thumbnail-size;
|
||||
|
||||
img {
|
||||
max-width: $item-md-thumbnail-size;
|
||||
max-height: $item-md-thumbnail-size;
|
||||
}
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin: 0 0 2px;
|
||||
font-size: 2.4rem;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin: 2px 0 2px;
|
||||
font-size: 1.6rem;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
line-height: normal;
|
||||
margin: 2px 0 2px;
|
||||
font-size: 1.4rem;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
p {
|
||||
line-height: normal;
|
||||
color: #666;
|
||||
font-size: 1.4rem;
|
||||
margin: 0 0 2px;
|
||||
}
|
||||
|
||||
button.item.activated {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
ion-item-options {
|
||||
button, [button] {
|
||||
height: calc(100% - 2px);
|
||||
margin: 1px 0 1px 0;
|
||||
box-shadow: none;
|
||||
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
|
||||
&:before{
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.list {
|
||||
margin: 0 $list-md-margin-right $list-md-margin-bottom $list-md-margin-left;
|
||||
|
||||
@@ -27,53 +213,58 @@ $list-md-header-color: #858585 !default;
|
||||
color: $list-md-header-color;
|
||||
}
|
||||
|
||||
+ .list {
|
||||
margin-top: $list-md-margin-top + $list-md-margin-bottom;
|
||||
|
||||
ion-header {
|
||||
margin-top: -$list-md-margin-top;
|
||||
padding-top: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.list + .list {
|
||||
margin-top: $list-md-margin-top + $list-md-margin-bottom;
|
||||
}
|
||||
|
||||
.list + .list ion-header {
|
||||
margin-top: -$list-md-margin-top;
|
||||
padding-top: 0;
|
||||
}
|
||||
/**************/
|
||||
/* INSET LIST */
|
||||
/**************/
|
||||
|
||||
.list[inset] {
|
||||
margin: $list-inset-md-margin-top $list-inset-md-margin-right $list-inset-md-margin-bottom $list-inset-md-margin-left;
|
||||
border-radius: $list-inset-md-border-radius;
|
||||
|
||||
.item:first-child {
|
||||
border-top-width: 0;
|
||||
margin-top: 0;
|
||||
border-top-right-radius: $list-inset-md-border-radius;
|
||||
border-top-left-radius: $list-inset-md-border-radius;
|
||||
|
||||
&:before {
|
||||
border-top: none;
|
||||
}
|
||||
}
|
||||
|
||||
.item:last-child {
|
||||
border-bottom-width: 0;
|
||||
margin-bottom: 0;
|
||||
border-bottom-right-radius: $list-inset-md-border-radius;
|
||||
border-bottom-left-radius: $list-inset-md-border-radius;
|
||||
}
|
||||
}
|
||||
|
||||
.list[inset] .item:not(ion-input):last-child:after {
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
.list[inset] + .list[inset] {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.list[no-lines] {
|
||||
ion-header + .item:before {
|
||||
border-width: 1px;
|
||||
.item:not(ion-input):last-child:after {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.item:before,
|
||||
.item:after {
|
||||
+ .list[inset] {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*****************/
|
||||
/* NO LINES LIST */
|
||||
/*****************/
|
||||
|
||||
.list[no-lines] {
|
||||
ion-header,
|
||||
ion-item-group-title,
|
||||
.item,
|
||||
.item .item-inner {
|
||||
border-width: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<ion-content class="outer-content">
|
||||
<ion-list no-lines>
|
||||
<ion-header>
|
||||
List Header
|
||||
List With No Lines
|
||||
</ion-header>
|
||||
|
||||
<ion-switch>
|
||||
@@ -27,4 +27,94 @@
|
||||
</ion-note>
|
||||
</ion-item>
|
||||
</ion-list>
|
||||
|
||||
<ion-list>
|
||||
<ion-header>
|
||||
List With No Lines First Item
|
||||
</ion-header>
|
||||
|
||||
<ion-item no-lines>
|
||||
<icon pizza item-left></icon>
|
||||
Pizza
|
||||
<ion-note item-right>
|
||||
Always
|
||||
</ion-note>
|
||||
</ion-item>
|
||||
|
||||
<ion-item>
|
||||
<icon beer item-left></icon>
|
||||
Beer
|
||||
<ion-note item-right>
|
||||
Yes Plz
|
||||
</ion-note>
|
||||
</ion-item>
|
||||
|
||||
<ion-item>
|
||||
<icon wine item-left></icon>
|
||||
Wine
|
||||
<ion-note item-right>
|
||||
All the time
|
||||
</ion-note>
|
||||
</ion-item>
|
||||
</ion-list>
|
||||
|
||||
<ion-list>
|
||||
<ion-header>
|
||||
List With No Lines Middle Item
|
||||
</ion-header>
|
||||
|
||||
<ion-item>
|
||||
<icon pizza item-left></icon>
|
||||
Pizza
|
||||
<ion-note item-right>
|
||||
Always
|
||||
</ion-note>
|
||||
</ion-item>
|
||||
|
||||
<ion-item no-lines>
|
||||
<icon beer item-left></icon>
|
||||
Beer
|
||||
<ion-note item-right>
|
||||
Yes Plz
|
||||
</ion-note>
|
||||
</ion-item>
|
||||
|
||||
<ion-item>
|
||||
<icon wine item-left></icon>
|
||||
Wine
|
||||
<ion-note item-right>
|
||||
All the time
|
||||
</ion-note>
|
||||
</ion-item>
|
||||
</ion-list>
|
||||
|
||||
<ion-list>
|
||||
<ion-header>
|
||||
List With No Lines Last Item
|
||||
</ion-header>
|
||||
|
||||
<ion-item>
|
||||
<icon pizza item-left></icon>
|
||||
Pizza
|
||||
<ion-note item-right>
|
||||
Always
|
||||
</ion-note>
|
||||
</ion-item>
|
||||
|
||||
<ion-item>
|
||||
<icon beer item-left></icon>
|
||||
Beer
|
||||
<ion-note item-right>
|
||||
Yes Plz
|
||||
</ion-note>
|
||||
</ion-item>
|
||||
|
||||
<ion-item no-lines>
|
||||
<icon wine item-left></icon>
|
||||
Wine
|
||||
<ion-note item-right>
|
||||
All the time
|
||||
</ion-note>
|
||||
</ion-item>
|
||||
</ion-list>
|
||||
</ion-content>
|
||||
|
||||
@@ -9,7 +9,7 @@ ion-radio {
|
||||
@include user-select-none();
|
||||
}
|
||||
|
||||
ion-radio[aria-disabled=true] {
|
||||
ion-radio[aria-disabled=true] .item-inner > * {
|
||||
opacity: 0.5;
|
||||
color: $subdued-text-color;
|
||||
pointer-events: none;
|
||||
|
||||
@@ -182,12 +182,14 @@ export class RadioGroup extends Ion {
|
||||
'(click)': 'click($event)'
|
||||
},
|
||||
template:
|
||||
'<ion-item-content id="{{labelId}}">' +
|
||||
'<ng-content></ng-content>' +
|
||||
'</ion-item-content>' +
|
||||
'<media-radio>' +
|
||||
'<radio-icon></radio-icon>' +
|
||||
'</media-radio>'
|
||||
'<div class="item-inner">' +
|
||||
'<ion-item-content id="{{labelId}}">' +
|
||||
'<ng-content></ng-content>' +
|
||||
'</ion-item-content>' +
|
||||
'<media-radio>' +
|
||||
'<radio-icon></radio-icon>' +
|
||||
'</media-radio>' +
|
||||
'</div>'
|
||||
})
|
||||
export class RadioButton extends Ion {
|
||||
/**
|
||||
|
||||
@@ -29,7 +29,7 @@ ion-switch {
|
||||
}
|
||||
|
||||
media-switch {
|
||||
padding: 6px ($item-ios-padding-right / 2) 6px ($item-ios-padding-left);
|
||||
padding: 6px ($item-ios-padding-right / 2) 5px ($item-ios-padding-left);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ ion-switch media-switch {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
ion-switch[aria-disabled=true] {
|
||||
ion-switch[aria-disabled=true] .item-inner > * {
|
||||
pointer-events: none;
|
||||
opacity: 0.5;
|
||||
color: $subdued-text-color;
|
||||
|
||||
@@ -87,12 +87,14 @@ class MediaSwitch {
|
||||
},
|
||||
template:
|
||||
'<ng-content select="[item-left]"></ng-content>' +
|
||||
'<ion-item-content id="{{labelId}}">' +
|
||||
'<ng-content></ng-content>' +
|
||||
'</ion-item-content>' +
|
||||
'<media-switch disable-activated>' +
|
||||
'<switch-icon></switch-icon>' +
|
||||
'</media-switch>',
|
||||
'<div class="item-inner">' +
|
||||
'<ion-item-content id="{{labelId}}">' +
|
||||
'<ng-content></ng-content>' +
|
||||
'</ion-item-content>' +
|
||||
'<media-switch disable-activated>' +
|
||||
'<switch-icon></switch-icon>' +
|
||||
'</media-switch>' +
|
||||
`</div>`,
|
||||
directives: [MediaSwitch]
|
||||
})
|
||||
export class Switch {
|
||||
|
||||
@@ -79,6 +79,8 @@ export class Activator {
|
||||
}
|
||||
|
||||
disableActivated(ev) {
|
||||
if (ev.defaultPrevented) return true;
|
||||
|
||||
let targetEle = ev.target;
|
||||
for (let x = 0; x < 4; x++) {
|
||||
if (!targetEle) break;
|
||||
|
||||
@@ -18,7 +18,3 @@ md-ripple {
|
||||
|
||||
transform: scale(0.001) translateZ(0);
|
||||
}
|
||||
|
||||
ion-item-sliding md-ripple {
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
@@ -7,8 +7,8 @@ let startCoord = null;
|
||||
let pointerTolerance = 4;
|
||||
let lastTouch = 0;
|
||||
let lastActivated = 0;
|
||||
let disableNativeClickTime = 0;
|
||||
let disableNativeClickLimit = 1000;
|
||||
let disableNativeClickUntil = 0;
|
||||
let disableNativeClickAmount = 3000;
|
||||
let activator = null;
|
||||
let isTapPolyfill = false;
|
||||
let app = null;
|
||||
@@ -55,7 +55,7 @@ function touchEnd(ev) {
|
||||
if (!hasPointerMoved(pointerTolerance, startCoord, endCoord)) {
|
||||
console.debug('create click from touch');
|
||||
|
||||
setDisableNativeClick();;
|
||||
disableNativeClickUntil = Date.now() + disableNativeClickAmount;
|
||||
|
||||
let clickEvent = doc.createEvent('MouseEvents');
|
||||
clickEvent.initMouseEvent('click', true, true, win, 1, 0, 0, endCoord.x, endCoord.y, false, false, false, false, 0, null);
|
||||
@@ -78,7 +78,7 @@ function mouseDown(ev) {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
|
||||
} else if (lastTouch + disableNativeClickLimit < Date.now()) {
|
||||
} else if (lastTouch + disableNativeClickAmount < Date.now()) {
|
||||
pointerStart(ev);
|
||||
}
|
||||
}
|
||||
@@ -90,7 +90,7 @@ function mouseUp(ev) {
|
||||
ev.stopPropagation();
|
||||
}
|
||||
|
||||
if (lastTouch + disableNativeClickLimit < Date.now()) {
|
||||
if (lastTouch + disableNativeClickAmount < Date.now()) {
|
||||
pointerEnd(ev);
|
||||
}
|
||||
}
|
||||
@@ -131,7 +131,6 @@ function pointerCancel(ev) {
|
||||
console.debug('pointerCancel from', ev.type);
|
||||
activator && activator.clearState();
|
||||
moveListeners(false);
|
||||
setDisableNativeClick();
|
||||
}
|
||||
|
||||
function moveListeners(shouldAdd) {
|
||||
@@ -156,7 +155,7 @@ function setDisableNativeClick() {
|
||||
}
|
||||
|
||||
function isDisabledNativeClick() {
|
||||
return disableNativeClickTime > Date.now();
|
||||
return disableNativeClickUntil > Date.now();
|
||||
}
|
||||
|
||||
function click(ev) {
|
||||
|
||||
@@ -9,7 +9,7 @@ $input-label-ios-color: #7f7f7f !default;
|
||||
ion-card {
|
||||
|
||||
[text-input] {
|
||||
margin: $item-ios-padding-top ($item-ios-padding-right / 2) $item-ios-padding-bottom ($item-ios-padding-left / 2);
|
||||
margin: $item-ios-padding-top ($item-ios-padding-right / 2) $item-ios-padding-bottom 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
@@ -19,10 +19,14 @@ ion-card {
|
||||
}
|
||||
|
||||
ion-label {
|
||||
margin: $item-ios-padding-top ($item-ios-padding-right / 2) $item-ios-padding-bottom ($item-ios-padding-left / 2);
|
||||
margin: $item-ios-padding-top ($item-ios-padding-right / 2) $item-ios-padding-bottom 0;
|
||||
color: $input-label-ios-color;
|
||||
}
|
||||
|
||||
ion-label + [text-input] {
|
||||
margin-left: $item-ios-padding-left;
|
||||
}
|
||||
|
||||
[stacked-label] ion-label {
|
||||
font-size: 1.2rem;
|
||||
margin-bottom: 4px;
|
||||
@@ -30,6 +34,7 @@ ion-card {
|
||||
|
||||
[stacked-label] [text-input],
|
||||
[floating-label] [text-input] {
|
||||
margin-left: 0;
|
||||
margin-top: 8px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
@@ -30,10 +30,6 @@ ion-input {
|
||||
}
|
||||
}
|
||||
|
||||
ion-input.item {
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
ion-input [text-input] {
|
||||
flex: 1;
|
||||
background-color: $text-input-background-color;
|
||||
|
||||
@@ -20,8 +20,10 @@ import {Platform} from '../../platform/platform';
|
||||
'(mouseup)': 'pointerEnd($event)'
|
||||
},
|
||||
template:
|
||||
'<ng-content></ng-content>' +
|
||||
'<input [type]="type" aria-hidden="true" scroll-assist *ng-if="scrollAssist">',
|
||||
'<div class="item-inner">' +
|
||||
'<ng-content></ng-content>' +
|
||||
'<input [type]="type" aria-hidden="true" scroll-assist *ng-if="scrollAssist">' +
|
||||
'</div>',
|
||||
directives: [NgIf, forwardRef(() => InputScrollAssist)]
|
||||
})
|
||||
export class TextInput {
|
||||
|
||||
@@ -15,7 +15,7 @@ import {Tab} from '../components/tabs/tab';
|
||||
import {List, ListHeader} from '../components/list/list';
|
||||
import {Item} from '../components/item/item';
|
||||
import {ItemGroup, ItemGroupTitle} from '../components/item/item-group';
|
||||
import {ItemSliding, ItemSlidingOptionButton} from '../components/item/item-sliding';
|
||||
import {ItemSliding} from '../components/item/item-sliding';
|
||||
import {Toolbar, ToolbarTitle, ToolbarItem} from '../components/toolbar/toolbar';
|
||||
import {Icon} from '../components/icon/icon';
|
||||
import {Checkbox} from '../components/checkbox/checkbox';
|
||||
@@ -60,7 +60,6 @@ export const IONIC_DIRECTIVES = [
|
||||
ItemGroup,
|
||||
ItemGroupTitle,
|
||||
ItemSliding,
|
||||
ItemSlidingOptionButton,
|
||||
|
||||
// Slides
|
||||
Slides,
|
||||
|
||||
@@ -10,24 +10,24 @@ export class DragGesture extends Gesture {
|
||||
|
||||
listen() {
|
||||
super.listen();
|
||||
|
||||
this.on('panstart', ev => {
|
||||
if (this.onDragStart(ev) !== false) {
|
||||
this.dragging = true;
|
||||
}
|
||||
// ev.stopPropagation();
|
||||
})
|
||||
});
|
||||
|
||||
this.on('panmove', ev => {
|
||||
if (!this.dragging) return;
|
||||
if (this.onDrag(ev) === false) {
|
||||
this.dragging = false;
|
||||
}
|
||||
// ev.stopPropagation()
|
||||
});
|
||||
|
||||
this.on('panend', ev => {
|
||||
if (!this.dragging) return;
|
||||
this.onDragEnd(ev);
|
||||
this.dragging = false;
|
||||
// ev.stopPropagation()
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
"components/icon/icon",
|
||||
"components/item/item",
|
||||
"components/item/item-media",
|
||||
"components/item/item-sliding",
|
||||
"components/grid/grid",
|
||||
"components/text-input/text-input",
|
||||
"components/text-input/label",
|
||||
|
||||
@@ -199,25 +199,25 @@ export function hasFocusedTextInput() {
|
||||
return false;
|
||||
}
|
||||
|
||||
export function closest(ele, selector) {
|
||||
var matchesFn;
|
||||
let matchesFn;
|
||||
['matches','webkitMatchesSelector','mozMatchesSelector','msMatchesSelector'].some(fn => {
|
||||
if (typeof document.documentElement[fn] == 'function') {
|
||||
matchesFn = fn;
|
||||
}
|
||||
});
|
||||
|
||||
// find vendor prefix
|
||||
['matches','webkitMatchesSelector','mozMatchesSelector','msMatchesSelector','oMatchesSelector'].some(function(fn) {
|
||||
if (typeof document.body[fn] == 'function') {
|
||||
matchesFn = fn;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
})
|
||||
export function closest(ele, selector, checkSelf) {
|
||||
if (ele && matchesFn) {
|
||||
|
||||
// traverse parents
|
||||
while (ele !== null) {
|
||||
parent = ele.parentElement;
|
||||
if (parent!==null && parent[matchesFn](selector)) {
|
||||
return parent;
|
||||
// traverse parents
|
||||
ele = (checkSelf ? ele : ele.parentElement);
|
||||
|
||||
while (ele !== null) {
|
||||
if (ele[matchesFn](selector)) {
|
||||
return ele;
|
||||
}
|
||||
ele = ele.parentElement;
|
||||
}
|
||||
ele = parent;
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -233,10 +233,10 @@ export function removeElement(ele) {
|
||||
* to reduce DOM reads. Cache is cleared on a window resize.
|
||||
* @param {TODO} ele TODO
|
||||
*/
|
||||
export function getDimensions(ion) {
|
||||
export function getDimensions(ion, ele) {
|
||||
if (!ion._dimId) {
|
||||
ion._dimId = ++dimensionIds;
|
||||
if (ion._dimId % 100 === 0) {
|
||||
if (ion._dimId % 1000 === 0) {
|
||||
// periodically flush dimensions
|
||||
flushDimensionCache();
|
||||
}
|
||||
@@ -253,7 +253,7 @@ export function getDimensions(ion) {
|
||||
left: ele.offsetLeft,
|
||||
top: ele.offsetTop
|
||||
};
|
||||
|
||||
|
||||
} else {
|
||||
// do not cache bad values
|
||||
return { width: 0, height: 0, left: 0, top: 0 };
|
||||
|
||||
@@ -15,11 +15,6 @@
|
||||
transition: none !important;
|
||||
}
|
||||
|
||||
// Remove any hairline borders
|
||||
.no-border:after {
|
||||
background: none !important;
|
||||
}
|
||||
|
||||
.hide,
|
||||
[hidden],
|
||||
template,
|
||||
|
||||
Reference in New Issue
Block a user