Skip to content

Instantly share code, notes, and snippets.

@cr0ybot
Last active February 10, 2020 20:57
Show Gist options
  • Save cr0ybot/9f186c7dab6409cdda0a2fc23740a8be to your computer and use it in GitHub Desktop.
Save cr0ybot/9f186c7dab6409cdda0a2fc23740a8be to your computer and use it in GitHub Desktop.
Titanium IcoMoon Font Icons

Titanium IcoMoon Font Icons

IcoMoon is a fantastic service for putting together a lean collection of custom icons in a single font file for use on the web and, now in a Titanium app!

  1. On the IcoMoon Generate tab, make sure that the glyphs are named how you want to access them in the app. For instance, a gear icon might be named "settings".
  2. Generate and download your font files. Place you IcoMoon TTF font file and the selection.json file into app/assets/fonts.
  3. Place icon.js into your app/lib/ folder.

Now you can add a font icon anywhere in your Alloy view files as a label or button (or switch, experimental):

<Label id="settingsIcon" module="icon" icon="settings" />

If you add an id attribute, you can reference the icon label in your controller and even change the icon on the fly:

$.settingsIcon.setIcon('settings-open');

To create a label or button from within a controller, import the icon lib and pass $ as the second parameter. This is so that the styles from any classes you're adding can be applied (maybe there's a better way to do this?):

const { createLabel } = require('icon');

const iconLabel = createLabel({ icon: 'settings', classes: 'iconWhite' }, $);

If you'd like to use icon fonts in places like ListViews using ItemTemplates, you'll have to add the icon library to your Alloy globals object (see alloy.js example). Now you can reference the icon library in TSS files (see app.tss example).

<Alloy>
	<ItemTemplate name="icon">
		<Label class="icon" text="Alloy.Globals.icon.charMap.settings" />
	</ItemTemplate>
</Alloy>
/**
* Icon reference for places where icon module doesn't work, notably ListViews
*/
Alloy.Globals.icon = require('icon');
'.icon': {
font: {
fontWeight: 'normal',
fontFamily: Alloy.Globals.icon.fontFamily,
fontSize: Alloy.Globals.icon.defaultSize,
},
}
/**
* Icon module
* app/lib/icon.js
*
* Inserts icons into Labels, and Buttons from an IcoMoon font icon set
*
* Inspired by: https://github.com/MattMcFarland/com.mattmcfarland.fontawesome
*/
const fontFamily = 'icomoon';
const defaultSize = OS_IOS ? '24pt' : 24;
let iosSystem = {};
if (OS_IOS) iosSystem = {
share: Ti.UI.iOS.SystemButton.ACTION,
};
/**
* Read selection.json from IcoMoon to auto-generate char mapping
*/
const config = '/fonts/selection.json';
const file = Ti.Filesystem.getFile(Ti.Filesystem.resourcesDirectory, config);
const selection = JSON.parse(file.read().text);
//console.log(selection);
const charMap = selection.icons.reduce((obj, icon) => {
const { name, code } = icon.properties;
obj[name] = String.fromCodePoint(code);
return obj;
}, {});
//console.log('font icons', charMap);
function getIconChar(name) {
//console.log('geIconChar', name);
if (charMap.hasOwnProperty(name)) {
return charMap[name];
}
return name;
}
function setIconFont(orig, size) {
const font = orig || {};
font.fontWeight = 'normal';
font.fontFamily = fontFamily;
font.fontSize = size || font.fontSize || defaultSize;
return font;
}
function addIconToString(string, icon) {
if (string && string.trim() !== '') {
return icon + ' ' + string;
}
return icon;
}
function replaceIconInString(string, oldIcon, newIcon) {
let newString = string.replace(oldIcon, newIcon);
if (newString == string) {
newString = addIconToString(string, newIcon);
}
return newString;
}
function setIcon(icon) {
const prevIcon = `${this.iconChar}`;
//console.log('setIcon', this);
if (this.hasOwnProperty('text')) { // Label
//console.log('Label.setIcon:', icon);
this.iconChar = getIconChar(icon);
this.text = replaceIconInString(this.text, prevIcon, this.iconChar);
return;
}
else if (this.hasOwnProperty('title')) { // Button
//console.log('Button.setIcon:', icon);
this.iconChar = getIconChar(icon);
this.title = replaceIconInString(this.title, prevIcon, this.iconChar);
return;
}
}
/**
* Adds icon to a Label
*/
function createLabelIcon(args, $ = null) {
//console.log('Creating label icon:', args.icon);
args.text = args.text || '';
if (args.icon) {
args.iconChar = getIconChar(args.icon);
args.text = addIconToString(args.text, args.iconChar);
}
args.font = setIconFont(args.font, args.iconSize);
args.verticalAlign = Ti.UI.TEXT_VERTICAL_ALIGNMENT_TOP;
args.classes = args.classes ? args.classes : [];
if (typeof args.classes === 'string') {
args.classes = [args.classes];
}
args.classes.push('icon');
const $l = Ti.UI.createLabel(args);
$l.setIcon = setIcon;
if ($) {
const style = $.createStyle({
classes: args.classes,
apiName: 'Label',
});
$l.applyProperties(style);
}
return $l;
}
/**
* Adds icon to a Button
*/
function createButtonIcon(args, $ = null) {
//console.log('Creating button icon:', args);
args.title = args.title || '';
if (args.icon) {
if (OS_IOS && args.iosSystem && iosSystem.hasOwnProperty(args.icon)) {
args.systemButton = iosSystem[args.icon];
}
else {
args.iconChar = getIconChar(args.icon);
//args.title = addIconToString(args.title, args.iconChar);
args.title = args.iconChar;
}
}
if (OS_IOS && !args.style) {
args.style = Ti.UI.iOS.SystemButtonStyle.PLAIN;
}
args.font = setIconFont(args.font, args.iconSize);
args.classes = args.classes ? args.classes : [];
if (typeof args.classes === 'string') {
args.classes = [args.classes];
}
args.classes.push('icon');
const $b = Ti.UI.createButton(args);
$b.setIcon = setIcon;
if ($) {
const style = $.createStyle({
classes: args.classes,
apiName: 'Button',
});
$b.applyProperties(style);
}
return $b;
}
/**
* Adds icon to a Toggle Button
*
* NOTE: this probably needs some love
*/
function createSwitchIcon(args) {
//console.log('Creating switch icon:', args);
if (args.icon || (args.iconOn && args.iconOff)) {
_.defaults(args, {
value: false,
color: 'white',
//tintColor: 'blue',
titleOn: 'On',
titleOff: 'Off',
});
let vArgs = args;
_.defaults(vArgs, {
layout: 'horizontal',
height: Ti.UI.SIZE,
width: Ti.UI.SIZE,
//color: null,
//tintColor: 'blue',
});
let $v = Ti.UI.createView(vArgs);
let iArgs = {
font: args.font,
iconSize: args.iconSize,
color: args.value ? args.tintColor : args.color,
classes: ['icon', 'iconLeft'],
right: 5,
//touchEnabled: false,
};
if (args.iconOff && args.iconOn) {
iArgs.icon = args.value ? args.iconOn : args.iconOff;
}
else {
iArgs.icon = args.icon;
}
let $i = createLabelIcon(iArgs);
$i.setIcon = setIcon;
let $l = Ti.UI.createLabel({
font: args.font,
color: args.value ? args.tintColor : args.color,
text: args.value ? args.titleOn : args.titleOff,
//touchEnabled: false,
});
$v.add([$i, $l]);
$v.icon = $i;
$v.label = $l;
$v.setValue = function(val) {
$v.value = val;
$v.icon.color = $v.label.color = $v.value ? $v.tintColor : $v.color;
$v.label.text = $v.value ? $v.titleOn : $v.titleOff;
if ($v.iconOn && $v.iconOff) {
//Ti.API.debug('Updating icon: '+($v.value ? $v.iconOn : $v.iconOff));
$v.icon.setIcon($v.value ? $v.iconOn : $v.iconOff);
}
};
$v.addEventListener('click', function(e) {
$v.setValue(!$v.value);
});
$v.setIcon = $i.setIcon;
return $v;
}
return Ti.UI.createSwitch(args);
}
exports.fontFamily = fontFamily;
exports.defaultSize = defaultSize;
exports.charMap = charMap;
exports.getIconChar = getIconChar;
exports.createLabel = createLabelIcon;
exports.createButton = createButtonIcon;
exports.createSwitch = createSwitchIcon;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment