Skip to content

Commit

Permalink
Add support for multiple font pickers (#1)
Browse files Browse the repository at this point in the history
  • Loading branch information
samuelmeuli committed Feb 3, 2018
1 parent de0909b commit b008386
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 16 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ The following parameters can be passed to the constructor of the `FontPicker` cl
* **`apiKey` (required)**: Google API key (can be generated [here](https://developers.google.com/fonts/docs/developer_api#APIKey))
* **`defaultFont`**: Font that is selected on initialization (default: `'Open Sans'`)
* **`options`**: Object with additional (optional) parameters:
* **`name`**: If you have multiple font pickers on your site, you need to give them unique names (which may only consist of letters and digits). These names must also be appended to the font picker's ID and the `.apply-font` class name; e.g. if `{ name: 'main' }`, then use `#font-picker-main` and `.apply-font-main`
* **`families`**: If only specific fonts shall appear in the list, specify their names in an array (default: all font families)
* **`categories`**: Array of font categories – possible values: `'sans-serif', 'serif', 'display', handwriting', 'monospace'` (default: all categories)
* **`variants`**: Array of variants which the fonts must include and which will be downloaded; the first variant in the array will become the default variant (and will be used in the font picker and the `.apply-font` class); e.g. `['regular', 'italic', '700', '700italic']` (default: `['regular']`)
Expand Down
39 changes: 31 additions & 8 deletions src/FontPicker.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ import './scss/style.scss';
* https://developers.google.com/fonts/docs/developer_api)
* @param {string} defaultFont - Font that is selected on initialization (default: 'Open Sans')
* @param {Object} options - Object with additional (optional) parameters:
* @param {string} name - If you have multiple font pickers on your site, you need to give them
* unique names (which may only consist of letters and digits). These names must also be
* appended to the font picker's ID and the .apply-font class name.
* Example: if { name: 'main' }, then use #font-picker-main and .apply-font-main
* @param {string[]} families - If only specific fonts shall appear in the list, specify their
* names in an array
* @param {string[]} categories - Array of font categories
Expand Down Expand Up @@ -37,20 +41,28 @@ export default class FontPicker {
if (typeof options !== 'object') {
throw Error('options parameter is not an object');
}
if (options.name) {
if (typeof options.name !== 'string') {
throw Error('options.name parameter is not a string');
}
if (options.name.match(/[^0-9a-z]/i)) {
throw Error('options.name may only contain letters and digits');
}
}
if (options.families && !(options.families instanceof Array)) {
throw Error('families parameter is not an array');
throw Error('options.families parameter is not an array');
}
if (options.categories && !(options.categories instanceof Array)) {
throw Error('categories parameter is not an array');
throw Error('options.categories parameter is not an array');
}
if (options.variants && !(options.variants instanceof Array)) {
throw Error('variants parameter is not an array');
throw Error('options.variants parameter is not an array');
}
if (options.limit && typeof options.limit !== 'number') {
throw Error('limit parameter is not a number');
throw Error('options.limit parameter is not a number');
}
if (options.sort && typeof options.sort !== 'string') {
throw Error('sort parameter is not a string');
throw Error('options.sort parameter is not a string');
}
if (onChange && typeof onChange !== 'function') {
throw Error('onChange is not a function');
Expand All @@ -59,6 +71,13 @@ export default class FontPicker {
// default parameters
const newDefaultFont = defaultFont || 'Open Sans';
const newOptions = options;
if (options.name) {
this.name = `-${options.name}`;
}
else {
this.name = '';
}
newOptions.name = this.name;
if (!options.limit) {
newOptions.limit = 100;
}
Expand All @@ -81,11 +100,15 @@ export default class FontPicker {
*/
init() {
this.expanded = false;
const fontPickerDiv = document.getElementById('font-picker');

const fontPickerDiv = document.getElementById(`font-picker${this.name}`);
if (!fontPickerDiv) {
throw Error(`Missing div with id="font-picker${this.name}"`);
}

// HTML for dropdown button (name of active font and dropdown arrow)
this.dropdownButton = document.createElement('a');
this.dropdownButton.id = 'dropdown-button';
this.dropdownButton.classList.add('dropdown-button');
this.dropdownButton.role = 'button';
this.dropdownButton.tabIndex = 0;
this.dropdownButton.onclick = () => this.toggleExpanded();
Expand Down Expand Up @@ -164,7 +187,7 @@ export default class FontPicker {
let targetElement = e.target; // clicked element

do {
if (targetElement === document.getElementById('font-picker')) {
if (targetElement === document.getElementById(`font-picker${this.name}`)) {
// click inside font picker
return;
}
Expand Down
13 changes: 7 additions & 6 deletions src/js/FontHandler.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export default class FontHandler {
this.fonts = [];
this.onChange = onChange;
this.options = options;
this.name = options.name;
this.previewIndex = 0; // list index up to which font previews have been downloaded

// make default font active and download it (if necessary)
Expand All @@ -32,7 +33,7 @@ export default class FontHandler {
this.stylesheet.rel = 'stylesheet';
this.stylesheet.type = 'text/css';
let style = `
.apply-font {
.apply-font${this.name} {
font-family: "${this.activeFont.family}";
}
`;
Expand All @@ -42,23 +43,23 @@ export default class FontHandler {
if (defaultVariant.length === 1) {
if (defaultVariant[0] === 'regular') {
style += `
.apply-font, #font-picker > ul > li > a {
.apply-font${this.name}, #font-picker > ul > li > a {
font-weight: 400;
font-style: normal;
}
`;
}
else if (defaultVariant[0] === 'italic') {
style += `
.apply-font, #font-picker > ul > li > a {
.apply-font${this.name}, #font-picker > ul > li > a {
font-weight: 400;
font-style: italic;
}
`;
}
else {
style += `
.apply-font, #font-picker > ul > li > a {
.apply-font${this.name}, #font-picker > ul > li > a {
font-weight: ${defaultVariant[0]};
font-style: normal;
}
Expand All @@ -68,7 +69,7 @@ export default class FontHandler {
// both font weight and style are specified
else if (defaultVariant.length === 2) {
style += `
.apply-font, #font-picker > ul > li > a {
.apply-font${this.name}, #font-picker > ul > li > a {
font-weight: ${defaultVariant[0]};
font-style: ${defaultVariant[1]};
}
Expand Down Expand Up @@ -145,7 +146,7 @@ export default class FontHandler {
// apply font and set fallback fonts
const fallbackFont = this.activeFont.category === 'handwriting' ? 'cursive' : this.activeFont.category;
const style = `
.apply-font {
.apply-font${this.name} {
font-family: "${this.activeFont.family}", "${previousFont}", ${fallbackFont};
}
`;
Expand Down
4 changes: 2 additions & 2 deletions src/scss/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ $color-font-list: #EAEAEA;
$element-height: 35px;


#font-picker {
div[id^="font-picker"] {
display: inline-block;
width: 200px;
position: relative;
Expand All @@ -27,7 +27,7 @@ $element-height: 35px;
outline: none;
}

#dropdown-button {
.dropdown-button {
height: $element-height;
display: flex;
align-items: center;
Expand Down

0 comments on commit b008386

Please sign in to comment.