mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2026-03-13 10:22:08 +08:00
set button css by attrs
This commit is contained in:
@@ -1,25 +0,0 @@
|
||||
@import "../../globals.core";
|
||||
|
||||
// Button Sizes
|
||||
// --------------------------------------------------
|
||||
|
||||
$button-large-font-size: 2rem !default;
|
||||
$button-large-height: 2.8em !default;
|
||||
$button-large-padding: 1.0em !default;
|
||||
|
||||
$button-small-font-size: 1.3rem !default;
|
||||
$button-small-height: 2.1em !default;
|
||||
$button-small-padding: 0.9em !default;
|
||||
|
||||
|
||||
.button-large {
|
||||
padding: 0 $button-large-padding;
|
||||
min-height: $button-large-height;
|
||||
font-size: $button-large-font-size;
|
||||
}
|
||||
|
||||
.button-small {
|
||||
padding: 0 $button-small-padding;
|
||||
min-height: $button-small-height;
|
||||
font-size: $button-small-font-size;
|
||||
}
|
||||
@@ -1,16 +1,12 @@
|
||||
import {Directive, ElementRef, Renderer, Attribute} from 'angular2/angular2';
|
||||
import {Directive, ElementRef, Renderer, Attribute, Optional} from 'angular2/angular2';
|
||||
|
||||
import {Config} from '../../config/config';
|
||||
import {Toolbar} from '../toolbar/toolbar';
|
||||
|
||||
|
||||
/**
|
||||
* @name Button
|
||||
* @module ionic
|
||||
* @property [primary] - sets button color to default primary
|
||||
* @property [secondary] - sets button color to default secondary
|
||||
* @property [danger] - sets button color to default danger
|
||||
* @property [light] - sets button color to default light
|
||||
* @property [dark] - sets button color to default dark
|
||||
* @property [outline] - for an unfilled outline button
|
||||
* @property [clear] - for a transparent button that only shows text and icons
|
||||
* @property [round] - for a button with rounded corners
|
||||
@@ -36,10 +32,14 @@ export class Button {
|
||||
|
||||
constructor(
|
||||
config: Config,
|
||||
elementRef: ElementRef,
|
||||
renderer: Renderer,
|
||||
@Attribute('type') type: string
|
||||
private elementRef: ElementRef,
|
||||
private renderer: Renderer
|
||||
) {
|
||||
this._role = 'button'; // bar-button
|
||||
this._size = null; // large
|
||||
this._style = null; // outline
|
||||
this._display = null; // block
|
||||
this._colors = []; // primary
|
||||
|
||||
let element = elementRef.nativeElement;
|
||||
|
||||
@@ -49,16 +49,11 @@ export class Button {
|
||||
|
||||
if (element.hasAttribute('ion-item')) {
|
||||
// no need to put on these classes for an ion-item
|
||||
this._role = null;
|
||||
return;
|
||||
}
|
||||
|
||||
renderer.setElementClass(elementRef, 'button', true);
|
||||
|
||||
this.attrToClass(renderer, elementRef);
|
||||
|
||||
if (type) {
|
||||
renderer.setElementAttribute(elementRef, type, '');
|
||||
}
|
||||
this._readAttrs(element);
|
||||
|
||||
// figure out if and where the icon lives in the button
|
||||
let childNodes = element.childNodes;
|
||||
@@ -98,47 +93,65 @@ export class Button {
|
||||
|
||||
}
|
||||
|
||||
attrToClass(renderer, elementRef) {
|
||||
// looping through native dom attributes, eww
|
||||
// https://github.com/angular/angular/issues/1818
|
||||
afterContentInit() {
|
||||
this._assignCss(true);
|
||||
}
|
||||
|
||||
let element = elementRef.nativeElement;
|
||||
let attrs = element.attributes;
|
||||
let btnAttrs = [];
|
||||
|
||||
BUTTON_SIZE_ATTRS.forEach(buttonAttr => {
|
||||
if (element.hasAttribute(buttonAttr)) {
|
||||
renderer.setElementClass(elementRef, 'button-' + buttonAttr, true);
|
||||
}
|
||||
});
|
||||
|
||||
BUTTON_TYPE_ATTRS.forEach(buttonAttr => {
|
||||
if (element.hasAttribute(buttonAttr)) {
|
||||
renderer.setElementClass(elementRef, 'button-' + buttonAttr, true);
|
||||
btnAttrs.push(buttonAttr);
|
||||
}
|
||||
});
|
||||
setRole(val) {
|
||||
this._role = val;
|
||||
}
|
||||
|
||||
_readAttrs(element) {
|
||||
let elementAttrs = element.attributes;
|
||||
let attrName;
|
||||
for (let i = 0, l = attrs.length; i < l; i++) {
|
||||
attrName = attrs[i].name;
|
||||
if (attrs[i].value === '' && COMMON_HTML_ATTR.test(attrName) !== true && BUTTON_TYPE_ATTRS.indexOf(attrName) < 0 && BUTTON_SIZE_ATTRS.indexOf(attrName) < 0) {
|
||||
if (btnAttrs.length) {
|
||||
btnAttrs.forEach(buttonAttr => {
|
||||
renderer.setElementClass(elementRef, 'button-' + buttonAttr + '-' + attrName, true);
|
||||
});
|
||||
} else {
|
||||
renderer.setElementClass(elementRef, 'button-' + attrName, true);
|
||||
}
|
||||
for (let i = 0, l = elementAttrs.length; i < l; i++) {
|
||||
if (elementAttrs[i].value !== '') continue;
|
||||
|
||||
attrName = elementAttrs[i].name;
|
||||
|
||||
if (BUTTON_STYLE_ATTRS.indexOf(attrName) > -1) {
|
||||
this._style = attrName;
|
||||
|
||||
} else if (BUTTON_DISPLAY_ATTRS.indexOf(attrName) > -1) {
|
||||
this._display = attrName;
|
||||
|
||||
} else if (BUTTON_SIZE_ATTRS.indexOf(attrName) > -1) {
|
||||
this._size = attrName;
|
||||
|
||||
} else if (!(IGNORE_ATTRS.test(attrName))) {
|
||||
this._colors.push(attrName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_assignCss(assignCssClass) {
|
||||
let setElementClass = this.renderer.setElementClass;
|
||||
let elementRef = this.elementRef;
|
||||
let role = this._role;
|
||||
if (role) {
|
||||
setElementClass(elementRef, role, assignCssClass); // button
|
||||
if (this._style) setElementClass(elementRef, role + '-' + this._style, assignCssClass); // button-clear
|
||||
if (this._display) setElementClass(elementRef, role + '-' + this._display, assignCssClass); // button-full
|
||||
if (this._size) setElementClass(elementRef, role + '-' + this._size, assignCssClass); // button-small
|
||||
this._colors.forEach(color => {
|
||||
setElementClass(elementRef, role + '-' + color, assignCssClass); // button-secondary
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
static setRoles(contentButtonChildren, role) {
|
||||
let buttons = contentButtonChildren.toArray();
|
||||
buttons.forEach(button => {
|
||||
button.setRole(role);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const COMMON_HTML_ATTR = /id|class|type|href|ng-/;
|
||||
const BUTTON_TYPE_ATTRS = ['block', 'full', 'round', 'clear', 'outline'];
|
||||
const BUTTON_SIZE_ATTRS = ['large', 'small'];
|
||||
const BUTTON_STYLE_ATTRS = ['round', 'clear', 'outline', 'fab'];
|
||||
const BUTTON_DISPLAY_ATTRS = ['block', 'full'];
|
||||
const IGNORE_ATTRS = /_ng/;
|
||||
|
||||
const TEXT = 1;
|
||||
const ICON = 2;
|
||||
|
||||
@@ -14,6 +14,13 @@ $button-ios-text-color: inverse($button-ios-color) !default;
|
||||
$button-ios-hover-opacity: 0.8 !default;
|
||||
$button-ios-border-radius: 4px !default;
|
||||
|
||||
$button-ios-large-font-size: 2rem !default;
|
||||
$button-ios-large-height: 2.8em !default;
|
||||
$button-ios-large-padding: 1.0em !default;
|
||||
$button-ios-small-font-size: 1.3rem !default;
|
||||
$button-ios-small-height: 2.1em !default;
|
||||
$button-ios-small-padding: 0.9em !default;
|
||||
|
||||
|
||||
// iOS Default Button
|
||||
// --------------------------------------------------
|
||||
@@ -62,6 +69,22 @@ $button-ios-border-radius: 4px !default;
|
||||
}
|
||||
|
||||
|
||||
// iOS Button Sizes
|
||||
// --------------------------------------------------
|
||||
|
||||
.button-large {
|
||||
padding: 0 $button-ios-large-padding;
|
||||
min-height: $button-ios-large-height;
|
||||
font-size: $button-ios-large-font-size;
|
||||
}
|
||||
|
||||
.button-small {
|
||||
padding: 0 $button-ios-small-padding;
|
||||
min-height: $button-ios-small-height;
|
||||
font-size: $button-ios-small-font-size;
|
||||
}
|
||||
|
||||
|
||||
// iOS Block Button
|
||||
// --------------------------------------------------
|
||||
|
||||
@@ -160,4 +183,3 @@ $button-ios-border-radius: 4px !default;
|
||||
|
||||
@import "../button-fab";
|
||||
@import "../button-icon";
|
||||
@import "../button-size";
|
||||
|
||||
@@ -26,6 +26,13 @@ $button-md-color-activated: color-shade($button-md-color) !defaul
|
||||
$button-md-text-color: inverse($button-md-color) !default;
|
||||
$button-md-hover-opacity: 0.8 !default;
|
||||
|
||||
$button-md-large-font-size: 2rem !default;
|
||||
$button-md-large-height: 2.8em !default;
|
||||
$button-md-large-padding: 1.0em !default;
|
||||
$button-md-small-font-size: 1.3rem !default;
|
||||
$button-md-small-height: 2.1em !default;
|
||||
$button-md-small-padding: 0.9em !default;
|
||||
|
||||
|
||||
// Material Design Default Button
|
||||
// --------------------------------------------------
|
||||
@@ -87,15 +94,15 @@ $button-md-hover-opacity: 0.8 !default;
|
||||
// --------------------------------------------------
|
||||
|
||||
.button-large {
|
||||
padding: 0 $button-large-padding;
|
||||
min-height: $button-large-height;
|
||||
font-size: $button-large-font-size;
|
||||
padding: 0 $button-md-large-padding;
|
||||
min-height: $button-md-large-height;
|
||||
font-size: $button-md-large-font-size;
|
||||
}
|
||||
|
||||
.button-small {
|
||||
padding: 0 $button-small-padding;
|
||||
min-height: $button-small-height;
|
||||
font-size: $button-small-font-size;
|
||||
padding: 0 $button-md-small-padding;
|
||||
min-height: $button-md-small-height;
|
||||
font-size: $button-md-small-font-size;
|
||||
}
|
||||
|
||||
|
||||
@@ -254,4 +261,3 @@ $button-md-hover-opacity: 0.8 !default;
|
||||
|
||||
@import "../button-fab";
|
||||
@import "../button-icon";
|
||||
@import "../button-size";
|
||||
|
||||
160
ionic/components/button/test/button.spec.ts
Normal file
160
ionic/components/button/test/button.spec.ts
Normal file
@@ -0,0 +1,160 @@
|
||||
import {Button, Config} from 'ionic/ionic';
|
||||
|
||||
export function run() {
|
||||
|
||||
function mockButton(attrs, config) {
|
||||
config = config || new Config();
|
||||
let elementRef = {
|
||||
nativeElement: document.createElement('button')
|
||||
};
|
||||
if (attrs) {
|
||||
for (let i = 0; i < attrs.length; i++) {
|
||||
elementRef.nativeElement.setAttribute(attrs[i], '');
|
||||
}
|
||||
}
|
||||
let renderer = {
|
||||
setElementClass: function(elementRef, className, shouldAdd) {
|
||||
elementRef.nativeElement.classList[shouldAdd ? 'add' : 'remove'](className);
|
||||
}
|
||||
};
|
||||
return new Button(config, elementRef, renderer);
|
||||
}
|
||||
|
||||
function hasClass(button, className) {
|
||||
return button.elementRef.nativeElement.classList.contains(className);
|
||||
}
|
||||
|
||||
it('should set a different button role', () => {
|
||||
let b = mockButton(['outline', 'small', 'full', 'primary']);
|
||||
b.setRole('bar-button')
|
||||
b._assignCss(true);
|
||||
expect(hasClass(b, 'bar-button-outline')).toEqual(true);
|
||||
expect(hasClass(b, 'bar-button-small')).toEqual(true);
|
||||
expect(hasClass(b, 'bar-button-full')).toEqual(true);
|
||||
expect(hasClass(b, 'bar-button-primary')).toEqual(true);
|
||||
|
||||
expect(hasClass(b, 'button-outline')).toEqual(false);
|
||||
expect(hasClass(b, 'button-small')).toEqual(false);
|
||||
expect(hasClass(b, 'button-full')).toEqual(false);
|
||||
expect(hasClass(b, 'button-primary')).toEqual(false);
|
||||
});
|
||||
|
||||
it('should remove button color attributes and add different role', () => {
|
||||
let b = mockButton(['outline', 'small', 'full', 'primary']);
|
||||
b._assignCss(true);
|
||||
expect(hasClass(b, 'button-outline')).toEqual(true);
|
||||
expect(hasClass(b, 'button-small')).toEqual(true);
|
||||
expect(hasClass(b, 'button-full')).toEqual(true);
|
||||
expect(hasClass(b, 'button-primary')).toEqual(true);
|
||||
|
||||
b._assignCss(false);
|
||||
expect(hasClass(b, 'button-outline')).toEqual(false);
|
||||
expect(hasClass(b, 'button-small')).toEqual(false);
|
||||
expect(hasClass(b, 'button-full')).toEqual(false);
|
||||
expect(hasClass(b, 'button-primary')).toEqual(false);
|
||||
});
|
||||
|
||||
it('should read button color attributes', () => {
|
||||
let b = mockButton(['primary']);
|
||||
b._assignCss(true);
|
||||
expect(hasClass(b, 'button-primary')).toEqual(true);
|
||||
|
||||
b = mockButton(['primary', 'secondary']);
|
||||
b._assignCss(true);
|
||||
expect(hasClass(b, 'button-primary')).toEqual(true);
|
||||
expect(hasClass(b, 'button-secondary')).toEqual(true);
|
||||
|
||||
b = mockButton(['outline', 'small', 'full', 'primary']);
|
||||
b._assignCss(true);
|
||||
expect(hasClass(b, 'button-outline')).toEqual(true);
|
||||
expect(hasClass(b, 'button-small')).toEqual(true);
|
||||
expect(hasClass(b, 'button-full')).toEqual(true);
|
||||
expect(hasClass(b, 'button-primary')).toEqual(true);
|
||||
});
|
||||
|
||||
it('should read button style attributes', () => {
|
||||
let b = mockButton(['round']);
|
||||
b._assignCss(true);
|
||||
expect(hasClass(b, 'button-round')).toEqual(true);
|
||||
|
||||
b = mockButton(['clear']);
|
||||
b._assignCss(true);
|
||||
expect(hasClass(b, 'button-clear')).toEqual(true);
|
||||
|
||||
b = mockButton(['outline']);
|
||||
b._assignCss(true);
|
||||
expect(hasClass(b, 'button-outline')).toEqual(true);
|
||||
|
||||
b = mockButton(['fab']);
|
||||
b._assignCss(true);
|
||||
expect(hasClass(b, 'button-fab')).toEqual(true);
|
||||
|
||||
b = mockButton(['clear', 'outline', 'small', 'full']);
|
||||
b._assignCss(true);
|
||||
expect(hasClass(b, 'button-clear')).toEqual(false);
|
||||
expect(hasClass(b, 'button-outline')).toEqual(true);
|
||||
expect(hasClass(b, 'button-small')).toEqual(true);
|
||||
expect(hasClass(b, 'button-full')).toEqual(true);
|
||||
});
|
||||
|
||||
it('should read button display attributes', () => {
|
||||
let b = mockButton(['block']);
|
||||
b._assignCss(true);
|
||||
expect(hasClass(b, 'button-block')).toEqual(true);
|
||||
|
||||
b = mockButton(['full']);
|
||||
b._assignCss(true);
|
||||
expect(hasClass(b, 'button-full')).toEqual(true);
|
||||
|
||||
b = mockButton(['block', 'full']);
|
||||
b._assignCss(true);
|
||||
expect(hasClass(b, 'button-block')).toEqual(false);
|
||||
expect(hasClass(b, 'button-full')).toEqual(true);
|
||||
});
|
||||
|
||||
it('should read button size attributes', () => {
|
||||
let b = mockButton(['small']);
|
||||
b._assignCss(true);
|
||||
expect(hasClass(b, 'button-small')).toEqual(true);
|
||||
|
||||
b = mockButton(['large']);
|
||||
b._assignCss(true);
|
||||
expect(hasClass(b, 'button-large')).toEqual(true);
|
||||
|
||||
b = mockButton(['large', 'small']);
|
||||
b._assignCss(true);
|
||||
expect(hasClass(b, 'button-large')).toEqual(false);
|
||||
expect(hasClass(b, 'button-small')).toEqual(true);
|
||||
});
|
||||
|
||||
it('should not add button css class for ion-item attribute', () => {
|
||||
let b = mockButton(['ion-item']);
|
||||
b._assignCss(true);
|
||||
expect(hasClass(b, 'button')).toEqual(false);
|
||||
});
|
||||
|
||||
it('should add button css class', () => {
|
||||
let b = mockButton();
|
||||
b._assignCss(true);
|
||||
expect(hasClass(b, 'button')).toEqual(true);
|
||||
});
|
||||
|
||||
it('should add disable-hover css class', () => {
|
||||
let config = new Config({
|
||||
hoverCSS: false
|
||||
});
|
||||
let b = mockButton(null, config);
|
||||
|
||||
expect(hasClass(b, 'disable-hover')).toEqual(true);
|
||||
});
|
||||
|
||||
it('should set defaults', () => {
|
||||
let b = mockButton();
|
||||
expect(b._role).toEqual('button');
|
||||
expect(b._size).toEqual(null);
|
||||
expect(b._colors.length).toEqual(0);
|
||||
expect(b._style).toEqual(null);
|
||||
expect(b._display).toEqual(null);
|
||||
});
|
||||
|
||||
}
|
||||
@@ -1,9 +1,10 @@
|
||||
import {Component, Directive, Host, ElementRef, Optional, forwardRef, Inject} from 'angular2/angular2';
|
||||
import {Component, Directive, Host, ElementRef, Optional, forwardRef, Inject, ContentChildren, ContentChild, QueryList} from 'angular2/angular2';
|
||||
|
||||
import {Ion} from '../ion';
|
||||
import {Config} from '../../config/config';
|
||||
import {MenuToggle} from '../menu/menu-toggle';
|
||||
import {Navbar} from '../navbar/navbar';
|
||||
import {Button} from '../button/button';
|
||||
|
||||
|
||||
/**
|
||||
@@ -63,8 +64,8 @@ export class ToolbarBase extends Ion {
|
||||
/**
|
||||
* @name Toolbar
|
||||
* @description
|
||||
* The toolbar is generic bar that sits above content.
|
||||
* Unlike an `ionNavbar`, `ionToolbar` can be used for a subheader as well.
|
||||
* The toolbar is generic bar that sits above or below content.
|
||||
* Unlike an `Navbar`, `Toolbar` can be used for a subheader as well.
|
||||
* @usage
|
||||
* ```html
|
||||
* <ion-toolbar>
|
||||
@@ -89,6 +90,7 @@ export class ToolbarBase extends Ion {
|
||||
}
|
||||
})
|
||||
export class Toolbar extends ToolbarBase {
|
||||
|
||||
constructor(
|
||||
elementRef: ElementRef,
|
||||
config: Config
|
||||
@@ -101,14 +103,14 @@ export class Toolbar extends ToolbarBase {
|
||||
/**
|
||||
* @name ToolbarTitle
|
||||
* @description
|
||||
* `ion-title` is a component that sets the title of the `ionToolbar` or `ionNavbar`
|
||||
* `ion-title` is a component that sets the title of the `Toolbar` or `Navbar`
|
||||
* @usage
|
||||
* ```html
|
||||
* <ion-navbar *navbar>
|
||||
* <ion-title>Tab 1</ion-title>
|
||||
* </ion-navbar>
|
||||
*
|
||||
*<!-- or if you wanted to crate a subheader title-->
|
||||
*<!-- or if you wanted to create a subheader title-->
|
||||
* <ion-navbar *navbar>
|
||||
* <ion-title>Tab 1</ion-title>
|
||||
* </ion-navbar>
|
||||
@@ -159,4 +161,9 @@ export class ToolbarItem extends Ion {
|
||||
toolbar && toolbar.addItemRef(elementRef);
|
||||
navbar && navbar.addItemRef(elementRef);
|
||||
}
|
||||
|
||||
@ContentChildren(Button)
|
||||
set _buttons(buttons) {
|
||||
Button.setRoles(buttons, 'bar-button');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -301,7 +301,10 @@ export class Platform {
|
||||
* @returns {boolean} TODO
|
||||
*/
|
||||
testNavigatorPlatform(navigatorPlatformExpression) {
|
||||
return navigatorPlatformExpression.test(this._bPlt || '');
|
||||
if (navigatorPlatformExpression && this._bPlt) {
|
||||
let rgx = new RegExp(navigatorPlatformExpression, 'i');
|
||||
return rgx.test(this._bPlt);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -52,7 +52,7 @@ Platform.register({
|
||||
// however, under-powered devices shouldn't use ripple
|
||||
// if this a linux device, and is using Android Chrome v36 (Android 5.0)
|
||||
// or above then use ripple, otherwise do not use a ripple effect
|
||||
if (p.testNavigatorPlatform('/linux/i')) {
|
||||
if (p.testNavigatorPlatform(/linux/i)) {
|
||||
let chromeVersion = p.matchUserAgentVersion(/Chrome\/(\d+).(\d+)?/);
|
||||
if (chromeVersion) {
|
||||
// linux android device using modern android chrome browser gets ripple
|
||||
|
||||
Reference in New Issue
Block a user