Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions JSTokenField.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@
1A1A06C413FEE2D900CA6645 /* tokenNormal@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 1A1A06C013FEE2D900CA6645 /* tokenNormal@2x.png */; };
1A1A06CF13FF000C00CA6645 /* AddressBook.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A1A06CD13FF000C00CA6645 /* AddressBook.framework */; };
1A1A06D013FF000C00CA6645 /* AddressBookUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A1A06CE13FF000C00CA6645 /* AddressBookUI.framework */; };
8223ECC516672B0100221221 /* tokenHighlightedDark.png in Resources */ = {isa = PBXBuildFile; fileRef = 8223ECC116672B0100221221 /* tokenHighlightedDark.png */; };
8223ECC616672B0100221221 /* tokenHighlightedDark@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 8223ECC216672B0100221221 /* tokenHighlightedDark@2x.png */; };
8223ECC716672B0100221221 /* tokenNormalDark.png in Resources */ = {isa = PBXBuildFile; fileRef = 8223ECC316672B0100221221 /* tokenNormalDark.png */; };
8223ECC816672B0100221221 /* tokenNormalDark@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 8223ECC416672B0100221221 /* tokenNormalDark@2x.png */; };
B71650D1144399F800EBF2C7 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A1A069C13FEDEEC00CA6645 /* Foundation.framework */; };
B71650DB14439A0500EBF2C7 /* JSTokenField.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A1A06B913FEE01C00CA6645 /* JSTokenField.h */; };
B71650DC14439A0500EBF2C7 /* JSTokenField.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A06BA13FEE01C00CA6645 /* JSTokenField.m */; };
Expand Down Expand Up @@ -54,6 +58,10 @@
1A1A06C013FEE2D900CA6645 /* tokenNormal@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "tokenNormal@2x.png"; sourceTree = "<group>"; };
1A1A06CD13FF000C00CA6645 /* AddressBook.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AddressBook.framework; path = System/Library/Frameworks/AddressBook.framework; sourceTree = SDKROOT; };
1A1A06CE13FF000C00CA6645 /* AddressBookUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AddressBookUI.framework; path = System/Library/Frameworks/AddressBookUI.framework; sourceTree = SDKROOT; };
8223ECC116672B0100221221 /* tokenHighlightedDark.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = tokenHighlightedDark.png; sourceTree = "<group>"; };
8223ECC216672B0100221221 /* tokenHighlightedDark@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "tokenHighlightedDark@2x.png"; sourceTree = "<group>"; };
8223ECC316672B0100221221 /* tokenNormalDark.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = tokenNormalDark.png; sourceTree = "<group>"; };
8223ECC416672B0100221221 /* tokenNormalDark@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "tokenNormalDark@2x.png"; sourceTree = "<group>"; };
B71650D0144399F800EBF2C7 /* libJSTokenFieldLibrary.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libJSTokenFieldLibrary.a; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */

Expand Down Expand Up @@ -131,6 +139,10 @@
1A1A06A113FEDEEC00CA6645 /* Supporting Files */ = {
isa = PBXGroup;
children = (
8223ECC116672B0100221221 /* tokenHighlightedDark.png */,
8223ECC216672B0100221221 /* tokenHighlightedDark@2x.png */,
8223ECC316672B0100221221 /* tokenNormalDark.png */,
8223ECC416672B0100221221 /* tokenNormalDark@2x.png */,
1A1A06A213FEDEEC00CA6645 /* JSTokenField-Info.plist */,
1A1A06A313FEDEEC00CA6645 /* InfoPlist.strings */,
1A1A06A613FEDEEC00CA6645 /* main.m */,
Expand Down Expand Up @@ -230,6 +242,10 @@
1A1A06C213FEE2D900CA6645 /* tokenHighlighted@2x.png in Resources */,
1A1A06C313FEE2D900CA6645 /* tokenNormal.png in Resources */,
1A1A06C413FEE2D900CA6645 /* tokenNormal@2x.png in Resources */,
8223ECC516672B0100221221 /* tokenHighlightedDark.png in Resources */,
8223ECC616672B0100221221 /* tokenHighlightedDark@2x.png in Resources */,
8223ECC716672B0100221221 /* tokenNormalDark.png in Resources */,
8223ECC816672B0100221221 /* tokenNormalDark@2x.png in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
16 changes: 15 additions & 1 deletion JSTokenField/DemoViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

#import "DemoViewController.h"
#import "JSTokenField.h"
#import "JSTokenButton.h"

@implementation DemoViewController

Expand Down Expand Up @@ -62,7 +63,13 @@ - (void)viewDidLoad
[[_toField label] setText:@"To:"];
[_toField setDelegate:self];
[self.view addSubview:_toField];


//Enable to change default button texture and title color
[JSTokenButton setDefaultHighlightedButtonImage:[[UIImage imageNamed:@"tokenHighlightedDark"] stretchableImageWithLeftCapWidth:14 topCapHeight:0]];
[JSTokenButton setDefaultNormalButtonImage:[[UIImage imageNamed:@"tokenNormalDark"] stretchableImageWithLeftCapWidth:14 topCapHeight:0]];
[JSTokenButton setDefaultNormalButtonTitleColor:[UIColor whiteColor]];
[JSTokenButton setDefaultHighlightedButtonTitleColor:[UIColor blackColor]];

UIView *separator1 = [[[UIView alloc] initWithFrame:CGRectMake(0, _toField.bounds.size.height-1, _toField.bounds.size.width, 1)] autorelease];
[separator1 setAutoresizingMask:UIViewAutoresizingFlexibleTopMargin];
[_toField addSubview:separator1];
Expand Down Expand Up @@ -160,4 +167,11 @@ - (void)handleTokenFieldFrameDidChange:(NSNotification *)note
}
}

- (void)tokenField:(JSTokenField *)tokenField token:(JSTokenButton *)tokBtn toggledTo:(BOOL)toggleValue {
NSLog(@"Token %@ toggled to %d", tokBtn.representedObject, toggleValue);
}

- (void)tokenField:(JSTokenField *)tokenField tokenTouchedUpInside:(JSTokenButton *)tokBtn {
NSLog(@"Token button %@ touched", tokBtn.representedObject);
}
@end
11 changes: 10 additions & 1 deletion JSTokenField/JSTokenButton.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@
UIImage *_highlightedBg;

id _representedObject;

}

@property (nonatomic, getter=isToggled) BOOL toggled;
Expand All @@ -48,7 +47,17 @@
@property (nonatomic, retain) id representedObject;

@property (nonatomic, assign) JSTokenField *parentField;
@property (nonatomic, strong) UIColor *normalTitleColor;
@property (nonatomic, strong) UIColor *highlightedTitleColor;


+ (JSTokenButton *)tokenWithString:(NSString *)string representedObject:(id)obj;
+ (JSTokenButton *)tokenWithString:(NSString *)string representedObject:(id)obj normalBG:(UIImage *)nbg highlightedBG:(UIImage *)hbg normalTitleColor:(UIColor *)normalTColor highlightedTitleColor:(UIColor *)hiTColor;


//Customization related methods
+ (void)setDefaultNormalButtonImage:(UIImage *)image;
+ (void)setDefaultHighlightedButtonImage:(UIImage *)image;
+ (void)setDefaultNormalButtonTitleColor:(UIColor *)nColor;
+ (void)setDefaultHighlightedButtonTitleColor:(UIColor *)hColor;
@end
100 changes: 94 additions & 6 deletions JSTokenField/JSTokenButton.m
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,84 @@ @implementation JSTokenButton
@synthesize representedObject = _representedObject;
@synthesize parentField = _parentField;

/*- (id)init
{
self = [super init];
if (self) {
self.ty
}
return self;
}*/

static __strong UIImage *_defaultNormalButtonImage = nil;
static __strong UIImage *_defaultHighlightedButtonImage = nil;
static __strong UIColor *_defaultNormalButtonTitleColor = nil;
static __strong UIColor *_defaultHighlightedButtonTitleColor = nil;

+ (JSTokenButton *)tokenWithString:(NSString *)string representedObject:(id)obj
{
return [JSTokenButton tokenWithString:string
representedObject:obj
normalBG:nil
highlightedBG:nil
normalTitleColor:nil
highlightedTitleColor:nil
];
}

+ (JSTokenButton *)tokenWithString:(NSString *)string representedObject:(id)obj normalBG:(UIImage *)nbg highlightedBG:(UIImage *)hbg normalTitleColor:(UIColor *)normalTColor highlightedTitleColor:(UIColor *)hiTColor {
JSTokenButton *button = (JSTokenButton *)[self buttonWithType:UIButtonTypeCustom];
[button setNormalBg:[[UIImage imageNamed:@"tokenNormal.png"] stretchableImageWithLeftCapWidth:14 topCapHeight:0]];
[button setHighlightedBg:[[UIImage imageNamed:@"tokenHighlighted.png"] stretchableImageWithLeftCapWidth:14 topCapHeight:0]];
if (nbg == nil) {
if (_defaultNormalButtonImage == nil) {
button.normalBg = [[UIImage imageNamed:@"tokenNormal"]
stretchableImageWithLeftCapWidth:14
topCapHeight:0];
}
else {
button.normalBg = _defaultNormalButtonImage;
}
}
else {
button.normalBg = nbg;
}
if (hbg == nil) {
if (_defaultHighlightedButtonImage == nil) {
button.highlightedBg = [[UIImage imageNamed:@"tokenHighlighted"]
stretchableImageWithLeftCapWidth:14
topCapHeight:0];
}
else {
button.highlightedBg = _defaultHighlightedButtonImage;
}
}
else {
button.highlightedBg = hbg;
}
[button setAdjustsImageWhenHighlighted:NO];
[button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
if (normalTColor == nil) {
if (_defaultNormalButtonTitleColor == nil) {
button.normalTitleColor = [UIColor blackColor];
}
else {
button.normalTitleColor = _defaultNormalButtonTitleColor;
}
}
else {
button.normalTitleColor = normalTColor;
}
if (hiTColor == nil) {
if (_defaultHighlightedButtonTitleColor == nil) {
button.highlightedTitleColor = [UIColor whiteColor];
}
else {
button.highlightedTitleColor = _defaultHighlightedButtonTitleColor;
}
}
else {
button.highlightedTitleColor = hiTColor;
}
[button setTitleColor:button.normalTitleColor forState:UIControlStateNormal];

[[button titleLabel] setFont:[UIFont fontWithName:@"Helvetica Neue" size:15]];
[[button titleLabel] setLineBreakMode:UILineBreakModeTailTruncation];
[button setTitleEdgeInsets:UIEdgeInsetsMake(2, 10, 0, 10)];
Expand All @@ -61,7 +132,7 @@ + (JSTokenButton *)tokenWithString:(NSString *)string representedObject:(id)obj

[button setRepresentedObject:obj];

return button;
return button;
}

- (void)setToggled:(BOOL)toggled
Expand All @@ -71,12 +142,12 @@ - (void)setToggled:(BOOL)toggled
if (_toggled)
{
[self setBackgroundImage:self.highlightedBg forState:UIControlStateNormal];
[self setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[self setTitleColor:self.highlightedTitleColor forState:UIControlStateNormal];
}
else
{
[self setBackgroundImage:self.normalBg forState:UIControlStateNormal];
[self setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[self setTitleColor:self.normalTitleColor forState:UIControlStateNormal];
}
}

Expand Down Expand Up @@ -121,4 +192,21 @@ - (BOOL)canBecomeFirstResponder {
return YES;
}

#pragma mark - Customization related methods

+ (void)setDefaultNormalButtonImage:(UIImage *)image {
_defaultNormalButtonImage = [image copy];
}

+ (void)setDefaultHighlightedButtonImage:(UIImage *)image {
_defaultHighlightedButtonImage = [image copy];
}

+ (void)setDefaultNormalButtonTitleColor:(UIColor *)nColor {
_defaultNormalButtonTitleColor = [nColor copy];
}

+ (void)setDefaultHighlightedButtonTitleColor:(UIColor *)hColor {
_defaultHighlightedButtonTitleColor = [hColor copy];
}
@end
7 changes: 7 additions & 0 deletions JSTokenField/JSTokenField.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,11 @@ extern NSString *const JSDeletedTokenKey;
- (void)removeTokenForString:(NSString *)string;
- (void)removeTokenWithRepresentedObject:(id)representedObject;

- (void)setNormalButtonImage:(UIImage *)image;
- (void)setHighlightedButtonImage:(UIImage *)image;
- (void)setNormalButtonTitleColor:(UIColor *)nColor;
- (void)setHighlightedButtonTitleColor:(UIColor *)hColor;

@end

@protocol JSTokenFieldDelegate <NSObject>
Expand All @@ -70,4 +75,6 @@ extern NSString *const JSDeletedTokenKey;
- (BOOL)tokenFieldShouldReturn:(JSTokenField *)tokenField;
- (void)tokenFieldDidEndEditing:(JSTokenField *)tokenField;

- (void)tokenField:(JSTokenField *)tokenField token:(JSTokenButton *)tokBtn toggledTo:(BOOL)toggleValue;
- (void)tokenField:(JSTokenField *)tokenField tokenTouchedUpInside:(JSTokenButton *)tokBtn;
@end
77 changes: 70 additions & 7 deletions JSTokenField/JSTokenField.m
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ - (JSTokenButton *)tokenWithString:(NSString *)string representedObject:(id)obj;
- (void)deleteHighlightedToken;

- (void)commonSetup;

@property (nonatomic, strong) UIImage *buttonNormalImage;
@property (nonatomic, strong) UIImage *buttonHightlightedImage;
@property (nonatomic, strong) UIColor *buttonNormalTitleColor;
@property (nonatomic, strong) UIColor *buttonHighlightedTitleColor;
@end


Expand Down Expand Up @@ -117,6 +122,10 @@ - (void)commonSetup {
selector:@selector(handleTextDidChange:)
name:UITextFieldTextDidChangeNotification
object:_textField];

//Initialize JSTokenButton background images to nil so the default background images are used by default
_buttonHightlightedImage = nil;
_buttonNormalImage = nil;
}

- (void)dealloc
Expand Down Expand Up @@ -146,7 +155,6 @@ - (void)addTokenWithTitle:(NSString *)string representedObject:(id)obj
{
[self.delegate tokenField:self didAddToken:aString representedObject:obj];
}

[self setNeedsLayout];
}
}
Expand Down Expand Up @@ -215,7 +223,12 @@ - (void)deleteHighlightedToken

- (JSTokenButton *)tokenWithString:(NSString *)string representedObject:(id)obj
{
JSTokenButton *token = [JSTokenButton tokenWithString:string representedObject:obj];
JSTokenButton *token = [JSTokenButton tokenWithString:string representedObject:obj
normalBG:self.buttonNormalImage
highlightedBG:self.buttonHightlightedImage
normalTitleColor:self.buttonNormalTitleColor
highlightedTitleColor:self.buttonHighlightedTitleColor];

CGRect frame = [token frame];

if (frame.size.width > self.frame.size.width)
Expand Down Expand Up @@ -295,12 +308,24 @@ - (void)toggle:(id)sender
{
for (JSTokenButton *token in _tokens)
{
[token setToggled:NO];
if (token != (JSTokenButton *)sender) {
[token setToggled:NO];
if ([self.delegate respondsToSelector:@selector(tokenField:token:toggledTo:)]) {
[self.delegate tokenField:self token:token toggledTo:NO];
}
}
else {
BOOL toggleValue = (token.isToggled)?NO:YES;
[token setToggled:toggleValue];
[token becomeFirstResponder];
if ([self.delegate respondsToSelector:@selector(tokenField:tokenTouchedUpInside:)]) {
[self.delegate tokenField:self tokenTouchedUpInside:token];
}
if ([self.delegate respondsToSelector:@selector(tokenField:token:toggledTo:)]) {
[self.delegate tokenField:self token:token toggledTo:toggleValue];
}
}
}

JSTokenButton *token = (JSTokenButton *)sender;
[token setToggled:YES];
[token becomeFirstResponder];
}

- (void)setFrame:(CGRect)frame
Expand All @@ -322,6 +347,44 @@ - (void)setFrame:(CGRect)frame
}
}

#pragma mark -
#pragma mark JSTokenButton customization methods
- (void)setNormalButtonImage:(UIImage *)image {
if (image != nil) {
self.buttonNormalImage = image;
for (JSTokenButton *token in _tokens) {
[token setNormalBg:self.buttonNormalImage];
}
}
}

- (void)setHighlightedButtonImage:(UIImage *)image {
if (image != nil) {
self.buttonHightlightedImage = image;
for (JSTokenButton *token in _tokens) {
[token setHighlightedBg:self.buttonHightlightedImage];
}
}
}

- (void)setNormalButtonTitleColor:(UIColor *)nColor {
if (nColor != nil) {
self.buttonNormalTitleColor = nColor;
for (JSTokenButton *token in _tokens) {
token.normalTitleColor = self.buttonNormalTitleColor;
}
}
}

- (void)setHighlightedButtonTitleColor:(UIColor *)hColor {
if (hColor != nil) {
self.buttonHighlightedTitleColor = hColor;
for (JSTokenButton *token in _tokens) {
token.highlightedTitleColor = self.buttonHighlightedTitleColor;
}
}
}

#pragma mark -
#pragma mark UITextFieldDelegate

Expand Down
Binary file added JSTokenField/tokenHighlightedDark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added JSTokenField/tokenHighlightedDark@2x.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added JSTokenField/tokenNormalDark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added JSTokenField/tokenNormalDark@2x.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.