font-picker
Advanced tools
Comparing version 1.2.1 to 1.3.0
1133
lib/index.js
@@ -7,680 +7,671 @@ (function (global, factory) { | ||
function __$$styleInject(css, ref) { | ||
if ( ref === void 0 ) ref = {}; | ||
var insertAt = ref.insertAt; | ||
/** | ||
* Check if font is available for the website | ||
* Source: https://www.kirupa.com/html5/detect_whether_font_is_installed.htm | ||
* @param fontName | ||
* @returns {boolean} | ||
*/ | ||
function isFontAvailable(fontName) { | ||
// creating our in-memory Canvas element where the magic happens | ||
var canvas = document.createElement("canvas"); | ||
var context = canvas.getContext("2d"); | ||
if (!css || typeof document === 'undefined') { return; } | ||
// the text whose final pixel size I want to measure | ||
var text = "abcdefghijklmnopqrstuvwxyz0123456789"; | ||
var head = document.head || document.getElementsByTagName('head')[0]; | ||
var style = document.createElement('style'); | ||
style.type = 'text/css'; | ||
// specifying the baseline font | ||
context.font = "72px monospace"; | ||
if (insertAt === 'top') { | ||
if (head.firstChild) { | ||
head.insertBefore(style, head.firstChild); | ||
} else { | ||
head.appendChild(style); | ||
} | ||
} else { | ||
head.appendChild(style); | ||
} | ||
// checking the size of the baseline text | ||
var baselineSize = context.measureText(text).width; | ||
if (style.styleSheet) { | ||
style.styleSheet.cssText = css; | ||
} else { | ||
style.appendChild(document.createTextNode(css)); | ||
} | ||
} | ||
// specifying the font whose existence we want to check | ||
context.font = "72px '" + fontName + "', monospace"; | ||
/** | ||
* Check if font is available for the website | ||
* Source: https://www.kirupa.com/html5/detect_whether_font_is_installed.htm | ||
* @param fontName | ||
* @returns {boolean} | ||
*/ | ||
function isFontAvailable(fontName) { | ||
// creating our in-memory Canvas element where the magic happens | ||
var canvas = document.createElement("canvas"); | ||
var context = canvas.getContext("2d"); | ||
// checking the size of the font we want to check | ||
var newSize = context.measureText(text).width; | ||
// the text whose final pixel size I want to measure | ||
var text = "abcdefghijklmnopqrstuvwxyz0123456789"; | ||
// removing the Canvas element we created | ||
canvas = null; | ||
// specifying the baseline font | ||
context.font = "72px monospace"; | ||
// checking the size of the baseline text | ||
var baselineSize = context.measureText(text).width; | ||
// specifying the font whose existence we want to check | ||
context.font = "72px '" + fontName + "', monospace"; | ||
// checking the size of the font we want to check | ||
var newSize = context.measureText(text).width; | ||
// removing the Canvas element we created | ||
canvas = null; | ||
// If the size of the two text instances is the same, the font does not exist because it is being | ||
// rendered using the default sans-serif font | ||
if (newSize == baselineSize) { | ||
return false; | ||
} else { | ||
return true; | ||
// If the size of the two text instances is the same, the font does not exist because it is being | ||
// rendered using the default sans-serif font | ||
if (newSize == baselineSize) { | ||
return false; | ||
} else { | ||
return true; | ||
} | ||
} | ||
} | ||
/** | ||
* Fetch list of all fonts available on Google Fonts, sorted by popularity | ||
*/ | ||
function fetchFontList(apiKey) { | ||
return new Promise(function (resolve, reject) { | ||
var url = 'https://www.googleapis.com/webfonts/v1/webfonts?sort=popularity&key=' + apiKey; | ||
var request = new XMLHttpRequest(); | ||
request.overrideMimeType('application/json'); | ||
request.open('GET', url, true); | ||
request.onreadystatechange = function () { | ||
// request has completed | ||
if (request.readyState === 4) { | ||
// success | ||
if (request.status === 200) { | ||
var response = JSON.parse(request.responseText); | ||
return resolve(response.items); | ||
/** | ||
* Fetch list of all fonts available on Google Fonts, sorted by popularity | ||
*/ | ||
function fetchFontList(apiKey) { | ||
return new Promise(function (resolve, reject) { | ||
var url = 'https://www.googleapis.com/webfonts/v1/webfonts?sort=popularity&key=' + apiKey; | ||
var request = new XMLHttpRequest(); | ||
request.overrideMimeType('application/json'); | ||
request.open('GET', url, true); | ||
request.onreadystatechange = function () { | ||
// request has completed | ||
if (request.readyState === 4) { | ||
// success | ||
if (request.status === 200) { | ||
var response = JSON.parse(request.responseText); | ||
return resolve(response.items); | ||
} | ||
// error | ||
else { | ||
return reject(new Error('Response has status code ' + request.status)); | ||
} | ||
} | ||
// error | ||
else { | ||
return reject(new Error('Response has status code ' + request.status)); | ||
} | ||
} | ||
}; | ||
request.send(); | ||
}); | ||
} | ||
/** | ||
* Add Google Fonts stylesheet for the specified font family and variants | ||
*/ | ||
function downloadFullFont(font, fontId, variants, onChange) { | ||
// generate the stylesheet URL | ||
var url = 'https://fonts.googleapis.com/css?family='; | ||
// font name | ||
url += font.family.replace(/ /g, '+'); | ||
// font variants | ||
url += ':' + variants[0]; | ||
for (var i = 1; i < variants.length; i += 1) { | ||
url += '|' + variants[i]; | ||
}; | ||
request.send(); | ||
}); | ||
} | ||
// add the stylesheet to the document head | ||
var link = document.createElement('link'); | ||
link.rel = 'stylesheet'; | ||
link.href = url; | ||
link.id = 'font-full-' + fontId; | ||
// if onChange function is specified: execute it once the stylesheet has loaded | ||
if (onChange) { | ||
link.onload = function () { | ||
onChange(font); | ||
}; | ||
/** | ||
* Add Google Fonts stylesheet for the specified font family and variants | ||
*/ | ||
function downloadFullFont(font, fontId, variants, onChange) { | ||
// generate the stylesheet URL | ||
var url = 'https://fonts.googleapis.com/css?family='; | ||
// font name | ||
url += font.family.replace(/ /g, '+'); | ||
// font variants | ||
url += ':' + variants[0]; | ||
for (var i = 1; i < variants.length; i += 1) { | ||
url += '|' + variants[i]; | ||
} | ||
// add the stylesheet to the document head | ||
var link = document.createElement('link'); | ||
link.rel = 'stylesheet'; | ||
link.href = url; | ||
link.id = 'font-full-' + fontId; | ||
// if onChange function is specified: execute it once the stylesheet has loaded | ||
if (onChange) { | ||
link.onload = function () { | ||
onChange(font); | ||
}; | ||
} | ||
document.head.appendChild(link); | ||
} | ||
document.head.appendChild(link); | ||
} | ||
/** | ||
* Add limited Google Fonts stylesheet for the specified font family (only containing the characters | ||
* which are needed to write the font family name) | ||
*/ | ||
function downloadPreviewFont(font, fontId, variants) { | ||
// generate the stylesheet URL | ||
var url = 'https://fonts.googleapis.com/css?family='; | ||
// font name | ||
url += font.family.replace(/ /g, '+'); | ||
// font variants | ||
url += ':' + variants[0]; | ||
for (var i = 1; i < variants.length; i += 1) { | ||
url += '|' + variants[i]; | ||
/** | ||
* Add limited Google Fonts stylesheet for the specified font family (only containing the characters | ||
* which are needed to write the font family name) | ||
*/ | ||
function downloadPreviewFont(font, fontId, variants) { | ||
// generate the stylesheet URL | ||
var url = 'https://fonts.googleapis.com/css?family='; | ||
// font name | ||
url += font.family.replace(/ /g, '+'); | ||
// font variants | ||
url += ':' + variants[0]; | ||
for (var i = 1; i < variants.length; i += 1) { | ||
url += '|' + variants[i]; | ||
} | ||
// characters to download: remove spaces and duplicate letters from the font name | ||
var downloadChars = font.family; | ||
downloadChars = downloadChars.replace(/\s+/g, ''); | ||
downloadChars = downloadChars.split('').filter(function (x, n, s) { | ||
return s.indexOf(x) === n; | ||
}).join(''); | ||
url += '&text=' + downloadChars; | ||
// add the stylesheet to the document head | ||
var link = document.createElement('link'); | ||
link.rel = 'stylesheet'; | ||
link.href = url; | ||
link.id = 'font-preview-' + fontId; | ||
document.head.appendChild(link); | ||
} | ||
// characters to download: remove spaces and duplicate letters from the font name | ||
var downloadChars = font.family; | ||
downloadChars = downloadChars.replace(/\s+/g, ''); | ||
downloadChars = downloadChars.split('').filter(function (x, n, s) { | ||
return s.indexOf(x) === n; | ||
}).join(''); | ||
url += '&text=' + downloadChars; | ||
// add the stylesheet to the document head | ||
var link = document.createElement('link'); | ||
link.rel = 'stylesheet'; | ||
link.href = url; | ||
link.id = 'font-preview-' + fontId; | ||
document.head.appendChild(link); | ||
} | ||
/** | ||
* Check whether the full font needs to be downloaded and do so if necessary | ||
*/ | ||
function checkFullFont(font, variants, onChange) { | ||
var fontId = font.family.replace(/\s+/g, '-').toLowerCase(); | ||
/** | ||
* Check whether the full font needs to be downloaded and do so if necessary | ||
*/ | ||
function checkFullFont(font, variants, onChange) { | ||
var fontId = font.family.replace(/\s+/g, '-').toLowerCase(); | ||
// if preview font is available: replace it with the full font | ||
if (document.getElementById('font-preview-' + fontId)) { | ||
document.getElementById('font-preview-' + fontId).outerHTML = ''; | ||
downloadFullFont(font, fontId, variants, onChange); | ||
} | ||
// if font is not available: download it | ||
else if (!document.getElementById('font-full-' + fontId) && !isFontAvailable(font.family)) { | ||
// if preview font is available: replace it with the full font | ||
if (document.getElementById('font-preview-' + fontId)) { | ||
document.getElementById('font-preview-' + fontId).outerHTML = ''; | ||
downloadFullFont(font, fontId, variants, onChange); | ||
} | ||
// if is available | ||
else if (onChange) { | ||
// execute onChange function if it is specified | ||
onChange(font); | ||
// if font is not available: download it | ||
else if (!document.getElementById('font-full-' + fontId) && !isFontAvailable(font.family)) { | ||
downloadFullFont(font, fontId, variants, onChange); | ||
} | ||
} | ||
// if is available | ||
else if (onChange) { | ||
// execute onChange function if it is specified | ||
onChange(font); | ||
} | ||
} | ||
/** | ||
* Check whether the preview font needs to be downloaded and do so if necessary | ||
*/ | ||
function checkPreviewFont(font, variants) { | ||
var fontId = font.family.replace(/\s+/g, '-').toLowerCase(); | ||
/** | ||
* Check whether the preview font needs to be downloaded and do so if necessary | ||
*/ | ||
function checkPreviewFont(font, variants) { | ||
var fontId = font.family.replace(/\s+/g, '-').toLowerCase(); | ||
// if full font is not available: download preview font | ||
if (!document.getElementById('font-full-' + fontId) && !isFontAvailable(font.family)) { | ||
downloadPreviewFont(font, fontId, variants); | ||
// if full font is not available: download preview font | ||
if (!document.getElementById('font-full-' + fontId) && !isFontAvailable(font.family)) { | ||
downloadPreviewFont(font, fontId, variants); | ||
} | ||
} | ||
} | ||
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { | ||
return typeof obj; | ||
} : function (obj) { | ||
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; | ||
}; | ||
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { | ||
return typeof obj; | ||
} : function (obj) { | ||
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; | ||
}; | ||
var classCallCheck = function (instance, Constructor) { | ||
if (!(instance instanceof Constructor)) { | ||
throw new TypeError("Cannot call a class as a function"); | ||
} | ||
}; | ||
var createClass = function () { | ||
function defineProperties(target, props) { | ||
for (var i = 0; i < props.length; i++) { | ||
var descriptor = props[i]; | ||
descriptor.enumerable = descriptor.enumerable || false; | ||
descriptor.configurable = true; | ||
if ("value" in descriptor) descriptor.writable = true; | ||
Object.defineProperty(target, descriptor.key, descriptor); | ||
} | ||
} | ||
return function (Constructor, protoProps, staticProps) { | ||
if (protoProps) defineProperties(Constructor.prototype, protoProps); | ||
if (staticProps) defineProperties(Constructor, staticProps); | ||
return Constructor; | ||
}; | ||
}(); | ||
/** | ||
* Class responsible for retrieving and filtering/sorting the font list, keeping track of the active | ||
* font, and downloading and applying fonts and font previews | ||
* @see FontPicker.js (same parameters) | ||
*/ | ||
var FontHandler = function () { | ||
/** | ||
* Download the default font (if necessary) and apply it | ||
*/ | ||
function FontHandler(apiKey, defaultFont, options, onChange) { | ||
classCallCheck(this, FontHandler); | ||
this.activeFont = defaultFont; | ||
this.apiKey = apiKey; | ||
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) | ||
this.activeFont = { | ||
family: defaultFont, | ||
variants: 'regular' | ||
}; | ||
checkFullFont(this.activeFont, this.options.variants); | ||
// apply default font | ||
this.stylesheet = document.createElement('style'); | ||
this.stylesheet.rel = 'stylesheet'; | ||
this.stylesheet.type = 'text/css'; | ||
var style = '\n\t\t\t.apply-font' + this.name + ' {\n\t\t\t\tfont-family: "' + this.activeFont.family + '";\n\t\t\t}\n\t\t'; | ||
// font weight/style: split number and text in font variant parameter | ||
var defaultVariant = this.options.variants[0].split(/(\d+)/).filter(Boolean); | ||
// either font weight or style is specified (e.g. 'regular, '300', 'italic') | ||
if (defaultVariant.length === 1) { | ||
if (defaultVariant[0] === 'regular') { | ||
style += '\n\t\t\t\t\t.apply-font' + this.name + ', #font-picker > ul > li > a {\n\t\t\t\t\t\tfont-weight: 400;\n\t\t\t\t\t\tfont-style: normal;\n\t\t\t\t\t}\n\t\t\t\t'; | ||
} else if (defaultVariant[0] === 'italic') { | ||
style += '\n\t\t\t\t\t.apply-font' + this.name + ', #font-picker > ul > li > a {\n\t\t\t\t\t\tfont-weight: 400;\n\t\t\t\t\t\tfont-style: italic;\n\t\t\t\t\t}\n\t\t\t\t'; | ||
} else { | ||
style += '\n\t\t\t\t\t.apply-font' + this.name + ', #font-picker > ul > li > a {\n\t\t\t\t\t\tfont-weight: ' + defaultVariant[0] + ';\n\t\t\t\t\t\tfont-style: normal;\n\t\t\t\t\t}\n\t\t\t\t'; | ||
} | ||
} | ||
// both font weight and style are specified | ||
else if (defaultVariant.length === 2) { | ||
style += '\n\t\t\t.apply-font' + this.name + ', #font-picker > ul > li > a {\n\t\t\t\tfont-weight: ' + defaultVariant[0] + ';\n\t\t\t\tfont-style: ' + defaultVariant[1] + ';\n\t\t\t}\n\t\t'; | ||
} | ||
this.stylesheet.appendChild(document.createTextNode(style)); | ||
document.head.appendChild(this.stylesheet); | ||
} | ||
var classCallCheck = function (instance, Constructor) { | ||
if (!(instance instanceof Constructor)) { | ||
throw new TypeError("Cannot call a class as a function"); | ||
} | ||
}; | ||
/** | ||
* Download list of available Google Fonts and filter/sort it according as specified in the | ||
* 'options' parameter object | ||
*/ | ||
var createClass = function () { | ||
function defineProperties(target, props) { | ||
for (var i = 0; i < props.length; i++) { | ||
var descriptor = props[i]; | ||
descriptor.enumerable = descriptor.enumerable || false; | ||
descriptor.configurable = true; | ||
if ("value" in descriptor) descriptor.writable = true; | ||
Object.defineProperty(target, descriptor.key, descriptor); | ||
} | ||
} | ||
return function (Constructor, protoProps, staticProps) { | ||
if (protoProps) defineProperties(Constructor.prototype, protoProps); | ||
if (staticProps) defineProperties(Constructor, staticProps); | ||
return Constructor; | ||
}; | ||
}(); | ||
createClass(FontHandler, [{ | ||
key: 'init', | ||
value: function init() { | ||
var _this = this; | ||
/** | ||
* Class responsible for retrieving and filtering/sorting the font list, keeping track of the active | ||
* font, and downloading and applying fonts and font previews | ||
* @see FontPicker.js (same parameters) | ||
*/ | ||
return fetchFontList(this.apiKey).then(function (fetchedList) { | ||
var fontList = fetchedList; | ||
var FontHandler = function () { | ||
// 'families' parameter (only keep fonts whose names are included in the provided array) | ||
if (_this.options.families) { | ||
fontList = fontList.filter(function (font) { | ||
return _this.options.families.includes(font.family); | ||
}); | ||
} | ||
/** | ||
* Download the default font (if necessary) and apply it | ||
*/ | ||
function FontHandler(apiKey, defaultFont, options, onChange) { | ||
classCallCheck(this, FontHandler); | ||
// 'categories' parameter (only keep fonts in categories from the provided array) | ||
if (_this.options.categories) { | ||
fontList = fontList.filter(function (font) { | ||
return _this.options.categories.includes(font.category); | ||
}); | ||
} | ||
// 'variants' parameter (only keep fonts with at least the specified variants) | ||
if (_this.options.variants) { | ||
fontList = fontList.filter(function (font) { | ||
for (var i = 0; i < _this.options.variants.length; i += 1) { | ||
if (font.variants.indexOf(_this.options.variants[i]) === -1) { | ||
return false; | ||
} | ||
} | ||
return true; | ||
}); | ||
} | ||
this.activeFont = defaultFont; | ||
this.apiKey = apiKey; | ||
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 | ||
// add default font to beginning of list if it is not already in it | ||
if (fontList.filter(function (font) { | ||
return font.family === _this.activeFont.family; | ||
}).length === 0) { | ||
fontList.unshift(_this.activeFont); | ||
} | ||
// make default font active and download it (if necessary) | ||
this.activeFont = { | ||
family: defaultFont, | ||
variants: 'regular' | ||
}; | ||
checkFullFont(this.activeFont, this.options.variants); | ||
// 'limit' parameter (limit font list size) | ||
if (_this.options.limit) { | ||
fontList = fontList.slice(0, _this.options.limit); | ||
} | ||
// apply default font | ||
this.stylesheet = document.createElement('style'); | ||
this.stylesheet.rel = 'stylesheet'; | ||
this.stylesheet.type = 'text/css'; | ||
var style = '\n\t\t\t.apply-font' + this.name + ' {\n\t\t\t\tfont-family: "' + this.activeFont.family + '";\n\t\t\t}\n\t\t'; | ||
// font weight/style: split number and text in font variant parameter | ||
var defaultVariant = this.options.variants[0].split(/(\d+)/).filter(Boolean); | ||
// either font weight or style is specified (e.g. 'regular, '300', 'italic') | ||
if (defaultVariant.length === 1) { | ||
if (defaultVariant[0] === 'regular') { | ||
style += '\n\t\t\t\t\t.apply-font' + this.name + ', #font-picker > ul > li > a {\n\t\t\t\t\t\tfont-weight: 400;\n\t\t\t\t\t\tfont-style: normal;\n\t\t\t\t\t}\n\t\t\t\t'; | ||
} else if (defaultVariant[0] === 'italic') { | ||
style += '\n\t\t\t\t\t.apply-font' + this.name + ', #font-picker > ul > li > a {\n\t\t\t\t\t\tfont-weight: 400;\n\t\t\t\t\t\tfont-style: italic;\n\t\t\t\t\t}\n\t\t\t\t'; | ||
} else { | ||
style += '\n\t\t\t\t\t.apply-font' + this.name + ', #font-picker > ul > li > a {\n\t\t\t\t\t\tfont-weight: ' + defaultVariant[0] + ';\n\t\t\t\t\t\tfont-style: normal;\n\t\t\t\t\t}\n\t\t\t\t'; | ||
// 'sort' parameter (list is already sorted by popularity) | ||
if (_this.options.sort === 'alphabetical') { | ||
fontList = fontList.sort(function (fontA, fontB) { | ||
return fontA.family.localeCompare(fontB.family); | ||
}); | ||
} | ||
// save modified font list | ||
_this.fonts = fontList; | ||
// download previews for the first 10 fonts in the list | ||
_this.downloadPreviews(10); | ||
}); | ||
} | ||
} | ||
// both font weight and style are specified | ||
else if (defaultVariant.length === 2) { | ||
style += '\n\t\t\t.apply-font' + this.name + ', #font-picker > ul > li > a {\n\t\t\t\tfont-weight: ' + defaultVariant[0] + ';\n\t\t\t\tfont-style: ' + defaultVariant[1] + ';\n\t\t\t}\n\t\t'; | ||
} | ||
this.stylesheet.appendChild(document.createTextNode(style)); | ||
document.head.appendChild(this.stylesheet); | ||
} | ||
/** | ||
* Download list of available Google Fonts and filter/sort it according as specified in the | ||
* 'options' parameter object | ||
*/ | ||
/** | ||
* Set the font with the given font list index as the active one, download (if necessary) and | ||
* apply it | ||
*/ | ||
}, { | ||
key: 'changeActiveFont', | ||
value: function changeActiveFont(index) { | ||
var previousFont = this.activeFont.family; | ||
createClass(FontHandler, [{ | ||
key: 'init', | ||
value: function init() { | ||
var _this = this; | ||
// change font | ||
this.activeFont = this.fonts[index]; | ||
return fetchFontList(this.apiKey).then(function (fetchedList) { | ||
var fontList = fetchedList; | ||
// apply font and set fallback fonts | ||
var fallbackFont = this.activeFont.category === 'handwriting' ? 'cursive' : this.activeFont.category; | ||
var style = '\n\t\t\t.apply-font' + this.name + ' {\n\t\t\t\tfont-family: "' + this.activeFont.family + '", "' + previousFont + '", ' + fallbackFont + ';\n\t\t\t}\n\t\t'; | ||
this.stylesheet.replaceChild(document.createTextNode(style), this.stylesheet.childNodes[0]); | ||
// 'families' parameter (only keep fonts whose names are included in the provided array) | ||
if (_this.options.families) { | ||
fontList = fontList.filter(function (font) { | ||
return _this.options.families.includes(font.family); | ||
}); | ||
} | ||
// download font (if necessary) | ||
checkFullFont(this.activeFont, this.options.variants, this.onChange); | ||
} | ||
// 'categories' parameter (only keep fonts in categories from the provided array) | ||
if (_this.options.categories) { | ||
fontList = fontList.filter(function (font) { | ||
return _this.options.categories.includes(font.category); | ||
}); | ||
} | ||
/** | ||
* Download font previews for the list entries up to the given index | ||
*/ | ||
// 'variants' parameter (only keep fonts with at least the specified variants) | ||
if (_this.options.variants) { | ||
fontList = fontList.filter(function (font) { | ||
for (var i = 0; i < _this.options.variants.length; i += 1) { | ||
if (font.variants.indexOf(_this.options.variants[i]) === -1) { | ||
return false; | ||
} | ||
} | ||
return true; | ||
}); | ||
}, { | ||
key: 'downloadPreviews', | ||
value: function downloadPreviews(downloadIndex) { | ||
// stop at the end of the font list | ||
var downloadIndexMax = void 0; | ||
if (downloadIndex > this.fonts.length) { | ||
downloadIndexMax = this.fonts.length; | ||
} else { | ||
downloadIndexMax = downloadIndex; | ||
} | ||
// add default font to beginning of list if it is not already in it | ||
if (fontList.filter(function (font) { | ||
return font.family === _this.activeFont.family; | ||
}).length === 0) { | ||
fontList.unshift(_this.activeFont); | ||
// download the previews up to the given index and apply them to the list entries | ||
for (var i = this.previewIndex; i < downloadIndexMax; i += 1) { | ||
checkPreviewFont(this.fonts[i], this.options.variants); | ||
var style = '\n\t\t\t\t.font-' + this.fonts[i].family.replace(/\s+/g, '-').toLowerCase() + ' {\n\t\t\t\t\tfont-family: "' + this.fonts[i].family + '";\n\t\t\t\t}\n\t\t\t'; | ||
this.stylesheet.appendChild(document.createTextNode(style)); | ||
} | ||
// 'limit' parameter (limit font list size) | ||
if (_this.options.limit) { | ||
fontList = fontList.slice(0, _this.options.limit); | ||
if (downloadIndexMax > this.previewIndex) { | ||
this.previewIndex = downloadIndexMax; | ||
} | ||
} | ||
}]); | ||
return FontHandler; | ||
}(); | ||
// 'sort' parameter (list is already sorted by popularity) | ||
if (_this.options.sort === 'alphabetical') { | ||
fontList = fontList.sort(function (fontA, fontB) { | ||
return fontA.family.localeCompare(fontB.family); | ||
}); | ||
} | ||
function styleInject(css, ref) { | ||
if ( ref === void 0 ) ref = {}; | ||
var insertAt = ref.insertAt; | ||
// save modified font list | ||
_this.fonts = fontList; | ||
if (!css || typeof document === 'undefined') { return; } | ||
// download previews for the first 10 fonts in the list | ||
_this.downloadPreviews(10); | ||
}); | ||
} | ||
var head = document.head || document.getElementsByTagName('head')[0]; | ||
var style = document.createElement('style'); | ||
style.type = 'text/css'; | ||
/** | ||
* Set the font with the given font list index as the active one, download (if necessary) and | ||
* apply it | ||
*/ | ||
if (insertAt === 'top') { | ||
if (head.firstChild) { | ||
head.insertBefore(style, head.firstChild); | ||
} else { | ||
head.appendChild(style); | ||
} | ||
} else { | ||
head.appendChild(style); | ||
} | ||
}, { | ||
key: 'changeActiveFont', | ||
value: function changeActiveFont(index) { | ||
var previousFont = this.activeFont.family; | ||
if (style.styleSheet) { | ||
style.styleSheet.cssText = css; | ||
} else { | ||
style.appendChild(document.createTextNode(css)); | ||
} | ||
} | ||
// change font | ||
this.activeFont = this.fonts[index]; | ||
var css = "@charset \"UTF-8\";\ndiv[id^=\"font-picker\"] {\n position: relative;\n display: inline-block;\n width: 200px;\n box-shadow: 1px 1px 3px rgba(0, 0, 0, 0.2); }\n div[id^=\"font-picker\"] * {\n box-sizing: border-box; }\n div[id^=\"font-picker\"] p {\n margin: 0;\n padding: 0; }\n div[id^=\"font-picker\"] a {\n color: inherit;\n cursor: pointer;\n outline: none;\n text-decoration: none; }\n div[id^=\"font-picker\"] .dropdown-button {\n height: 35px;\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 0 10px;\n background-color: #CBCBCB; }\n div[id^=\"font-picker\"] .dropdown-button:hover, div[id^=\"font-picker\"] .dropdown-button.expanded, div[id^=\"font-picker\"] .dropdown-button:focus {\n background-color: #bebebe; }\n div[id^=\"font-picker\"] .dropdown-button .dropdown-font-name {\n overflow: hidden;\n white-space: nowrap; }\n div[id^=\"font-picker\"] .dropdown-icon {\n margin-left: 10px; }\n\n@keyframes spinner {\n to {\n transform: rotate(360deg); } }\n div[id^=\"font-picker\"] .dropdown-icon.loading:before {\n content: '';\n display: block;\n height: 10px;\n width: 10px;\n border-radius: 50%;\n border: 2px solid #b2b2b2;\n border-top-color: black;\n animation: spinner 0.6s linear infinite; }\n div[id^=\"font-picker\"] .dropdown-icon.finished:before {\n content: '';\n display: block;\n height: 0;\n width: 0;\n border-left: 5px solid transparent;\n border-right: 5px solid transparent;\n border-top: 6px solid black;\n transition: transform 0.3s;\n margin: 0 2px; }\n div[id^=\"font-picker\"] .dropdown-icon.error:before {\n content: '⚠'; }\n div[id^=\"font-picker\"] .dropdown-button.expanded .dropdown-icon.finished:before {\n transform: rotate(-180deg); }\n div[id^=\"font-picker\"] ul {\n position: absolute;\n z-index: 1;\n max-height: 0;\n width: 100%;\n overflow-x: hidden;\n overflow-y: auto;\n -webkit-overflow-scrolling: touch;\n margin: 0;\n padding: 0;\n background-color: #EAEAEA;\n box-shadow: 1px 1px 3px rgba(0, 0, 0, 0.2);\n transition: 0.3s; }\n div[id^=\"font-picker\"] ul.expanded {\n max-height: 200px; }\n div[id^=\"font-picker\"] ul li {\n height: 35px;\n list-style: none; }\n div[id^=\"font-picker\"] ul li a {\n height: 100%;\n width: 100%;\n display: flex;\n align-items: center;\n padding: 0 10px;\n white-space: nowrap; }\n div[id^=\"font-picker\"] ul li a:hover, div[id^=\"font-picker\"] ul li a:focus {\n background-color: #dddddd; }\n div[id^=\"font-picker\"] ul li a.active-font {\n background-color: #d1d1d1; }\n"; | ||
styleInject(css); | ||
// apply font and set fallback fonts | ||
var fallbackFont = this.activeFont.category === 'handwriting' ? 'cursive' : this.activeFont.category; | ||
var style = '\n\t\t\t.apply-font' + this.name + ' {\n\t\t\t\tfont-family: "' + this.activeFont.family + '", "' + previousFont + '", ' + fallbackFont + ';\n\t\t\t}\n\t\t'; | ||
this.stylesheet.replaceChild(document.createTextNode(style), this.stylesheet.childNodes[0]); | ||
/** | ||
* Font picker interface | ||
* @param {string} apiKey (required) - Google API key (can be generated at | ||
* 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 | ||
* Possible values: 'sans-serif', 'serif', 'display', 'handwriting', 'monospace' (default: | ||
* all categories) | ||
* @param {string[]} 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) | ||
* Example: ['regular', 'italic', '700', '700italic'] (default: ['regular']) | ||
* @param {number} limit - Maximum number of fonts to be displayed in the list (the least popular | ||
* fonts will be omitted; default: 100) | ||
* @param {string} sort - Sorting attribute for the font list | ||
* Possible values: 'alphabetical' (default), 'popularity' | ||
* @param {function} onChange - Function which is executed whenever the user changes the active | ||
* font and its stylesheet finishes downloading | ||
*/ | ||
// download font (if necessary) | ||
checkFullFont(this.activeFont, this.options.variants, this.onChange); | ||
} | ||
var FontPicker = function () { | ||
function FontPicker(apiKey, defaultFont) { | ||
var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; | ||
var onChange = arguments[3]; | ||
classCallCheck(this, FontPicker); | ||
/** | ||
* Download font previews for the list entries up to the given index | ||
*/ | ||
// parameter validation | ||
if (!apiKey || typeof apiKey !== 'string') { | ||
throw Error('apiKey parameter is not a string or missing'); | ||
} | ||
if (defaultFont && typeof defaultFont !== 'string') { | ||
throw Error('defaultFont parameter is not a string'); | ||
} | ||
if ((typeof options === 'undefined' ? 'undefined' : _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('options.families parameter is not an array'); | ||
} | ||
if (options.categories && !(options.categories instanceof Array)) { | ||
throw Error('options.categories parameter is not an array'); | ||
} | ||
if (options.variants && !(options.variants instanceof Array)) { | ||
throw Error('options.variants parameter is not an array'); | ||
} | ||
if (options.limit && typeof options.limit !== 'number') { | ||
throw Error('options.limit parameter is not a number'); | ||
} | ||
if (options.sort && typeof options.sort !== 'string') { | ||
throw Error('options.sort parameter is not a string'); | ||
} | ||
if (onChange && typeof onChange !== 'function') { | ||
throw Error('onChange is not a function'); | ||
} | ||
}, { | ||
key: 'downloadPreviews', | ||
value: function downloadPreviews(downloadIndex) { | ||
// stop at the end of the font list | ||
var downloadIndexMax = void 0; | ||
if (downloadIndex > this.fonts.length) { | ||
downloadIndexMax = this.fonts.length; | ||
// default parameters | ||
var newDefaultFont = defaultFont || 'Open Sans'; | ||
var newOptions = options; | ||
if (options.name) { | ||
this.name = '-' + options.name; | ||
} else { | ||
downloadIndexMax = downloadIndex; | ||
this.name = ''; | ||
} | ||
// download the previews up to the given index and apply them to the list entries | ||
for (var i = this.previewIndex; i < downloadIndexMax; i += 1) { | ||
checkPreviewFont(this.fonts[i], this.options.variants); | ||
var style = '\n\t\t\t\t.font-' + this.fonts[i].family.replace(/\s+/g, '-').toLowerCase() + ' {\n\t\t\t\t\tfont-family: "' + this.fonts[i].family + '";\n\t\t\t\t}\n\t\t\t'; | ||
this.stylesheet.appendChild(document.createTextNode(style)); | ||
newOptions.name = this.name; | ||
if (!options.limit) { | ||
newOptions.limit = 100; | ||
} | ||
if (downloadIndexMax > this.previewIndex) { | ||
this.previewIndex = downloadIndexMax; | ||
if (!options.variants) { | ||
newOptions.variants = ['regular']; | ||
} | ||
} | ||
}]); | ||
return FontHandler; | ||
}(); | ||
if (!options.sort) { | ||
newOptions.sort = 'alphabetical'; | ||
} | ||
var css = "@charset \"UTF-8\";\ndiv[id^=\"font-picker\"] {\n display: inline-block;\n width: 200px;\n position: relative;\n box-shadow: 1px 1px 3px rgba(0, 0, 0, 0.2); }\n div[id^=\"font-picker\"] * {\n box-sizing: border-box; }\n div[id^=\"font-picker\"] p {\n margin: 0;\n padding: 0; }\n div[id^=\"font-picker\"] a {\n color: inherit;\n text-decoration: none;\n cursor: pointer;\n outline: none; }\n div[id^=\"font-picker\"] .dropdown-button {\n height: 35px;\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 0 10px;\n background-color: #CBCBCB; }\n div[id^=\"font-picker\"] .dropdown-button:hover, div[id^=\"font-picker\"] .dropdown-button.expanded, div[id^=\"font-picker\"] .dropdown-button:focus {\n background-color: #bebebe; }\n\n@keyframes spinner {\n to {\n transform: rotate(360deg); } }\n div[id^=\"font-picker\"] .dropdown-button .dropdown-icon.loading:before {\n content: '';\n display: block;\n height: 10px;\n width: 10px;\n border-radius: 50%;\n border: 2px solid #b2b2b2;\n border-top-color: black;\n animation: spinner 0.6s linear infinite; }\n div[id^=\"font-picker\"] .dropdown-button .dropdown-icon.finished:before {\n content: '▾'; }\n div[id^=\"font-picker\"] .dropdown-button .dropdown-icon.error:before {\n content: '⚠'; }\n div[id^=\"font-picker\"] ul {\n max-height: 0;\n width: 100%;\n position: absolute;\n z-index: 1;\n overflow-x: hidden;\n overflow-y: auto;\n -webkit-overflow-scrolling: touch;\n margin: 0;\n padding: 0;\n background-color: #EAEAEA;\n transition: 0.3s;\n box-shadow: 1px 1px 3px rgba(0, 0, 0, 0.2); }\n div[id^=\"font-picker\"] ul.expanded {\n max-height: 200px; }\n div[id^=\"font-picker\"] ul li {\n height: 35px;\n list-style: none; }\n div[id^=\"font-picker\"] ul li a {\n height: 100%;\n display: flex;\n align-items: center;\n padding: 0 10px;\n white-space: nowrap;\n width: 100%; }\n div[id^=\"font-picker\"] ul li a:hover, div[id^=\"font-picker\"] ul li a:focus {\n background-color: #dddddd; }\n div[id^=\"font-picker\"] ul li a.active-font {\n background-color: #d1d1d1; }\n"; | ||
__$$styleInject(css); | ||
// initialize FontHandler | ||
this.fontHandler = new FontHandler(apiKey, newDefaultFont, newOptions, onChange); | ||
/** | ||
* Font picker interface | ||
* @param {string} apiKey (required) - Google API key (can be generated at | ||
* 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 | ||
* Possible values: 'sans-serif', 'serif', 'display', 'handwriting', 'monospace' (default: | ||
* all categories) | ||
* @param {string[]} 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) | ||
* Example: ['regular', 'italic', '700', '700italic'] (default: ['regular']) | ||
* @param {number} limit - Maximum number of fonts to be displayed in the list (the least popular | ||
* fonts will be omitted; default: 100) | ||
* @param {string} sort - Sorting attribute for the font list | ||
* Possible values: 'alphabetical' (default), 'popularity' | ||
* @param {function} onChange - Function which is executed whenever the user changes the active | ||
* font and its stylesheet finishes downloading | ||
*/ | ||
var FontPicker = function () { | ||
function FontPicker(apiKey, defaultFont) { | ||
var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; | ||
var onChange = arguments[3]; | ||
classCallCheck(this, FontPicker); | ||
// parameter validation | ||
if (!apiKey || typeof apiKey !== 'string') { | ||
throw Error('apiKey parameter is not a string or missing'); | ||
// function bindings | ||
this.closeEventListener = this.closeEventListener.bind(this); | ||
} | ||
if (defaultFont && typeof defaultFont !== 'string') { | ||
throw Error('defaultFont parameter is not a string'); | ||
} | ||
if ((typeof options === 'undefined' ? 'undefined' : _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('options.families parameter is not an array'); | ||
} | ||
if (options.categories && !(options.categories instanceof Array)) { | ||
throw Error('options.categories parameter is not an array'); | ||
} | ||
if (options.variants && !(options.variants instanceof Array)) { | ||
throw Error('options.variants parameter is not an array'); | ||
} | ||
if (options.limit && typeof options.limit !== 'number') { | ||
throw Error('options.limit parameter is not a number'); | ||
} | ||
if (options.sort && typeof options.sort !== 'string') { | ||
throw Error('options.sort parameter is not a string'); | ||
} | ||
if (onChange && typeof onChange !== 'function') { | ||
throw Error('onChange is not a function'); | ||
} | ||
// default parameters | ||
var newDefaultFont = defaultFont || 'Open Sans'; | ||
var newOptions = options; | ||
if (options.name) { | ||
this.name = '-' + options.name; | ||
} else { | ||
this.name = ''; | ||
} | ||
newOptions.name = this.name; | ||
if (!options.limit) { | ||
newOptions.limit = 100; | ||
} | ||
if (!options.variants) { | ||
newOptions.variants = ['regular']; | ||
} | ||
if (!options.sort) { | ||
newOptions.sort = 'alphabetical'; | ||
} | ||
/** | ||
* Download list of available fonts and generate the font picker UI | ||
*/ | ||
// initialize FontHandler | ||
this.fontHandler = new FontHandler(apiKey, newDefaultFont, newOptions, onChange); | ||
// function bindings | ||
this.closeEventListener = this.closeEventListener.bind(this); | ||
} | ||
createClass(FontPicker, [{ | ||
key: 'init', | ||
value: function init() { | ||
var _this = this; | ||
/** | ||
* Download list of available fonts and generate the font picker UI | ||
*/ | ||
this.expanded = false; | ||
var fontPickerDiv = document.getElementById('font-picker' + this.name); | ||
if (!fontPickerDiv) { | ||
throw Error('Missing div with id="font-picker' + this.name + '"'); | ||
} | ||
createClass(FontPicker, [{ | ||
key: 'init', | ||
value: function init() { | ||
var _this = this; | ||
// HTML for dropdown button (name of active font and dropdown arrow) | ||
this.dropdownButton = document.createElement('a'); | ||
this.dropdownButton.classList.add('dropdown-button'); | ||
this.dropdownButton.role = 'button'; | ||
this.dropdownButton.tabIndex = 0; | ||
this.dropdownButton.onclick = function () { | ||
return _this.toggleExpanded(); | ||
}; | ||
this.dropdownButton.onkeypress = function () { | ||
return _this.toggleExpanded(); | ||
}; | ||
fontPickerDiv.appendChild(this.dropdownButton); | ||
// name of selected font | ||
this.dropdownFont = document.createElement('p'); | ||
this.dropdownFont.innerHTML = this.fontHandler.activeFont.family; | ||
this.dropdownFont.classList.add('dropdown-font-name'); | ||
this.dropdownButton.append(this.dropdownFont); | ||
// dropdown icon (possible classes/states: 'loading', 'finished', 'error') | ||
var dropdownIcon = document.createElement('p'); | ||
dropdownIcon.classList.add('dropdown-icon', 'loading'); | ||
this.dropdownButton.append(dropdownIcon); | ||
this.expanded = false; | ||
// HTML for font list | ||
this.ul = document.createElement('ul'); | ||
var fontPickerDiv = document.getElementById('font-picker' + this.name); | ||
if (!fontPickerDiv) { | ||
throw Error('Missing div with id="font-picker' + this.name + '"'); | ||
} | ||
// fetch font list, display dropdown arrow if successful | ||
this.fontHandler.init().then(function () { | ||
dropdownIcon.classList.remove('loading'); | ||
dropdownIcon.classList.add('finished'); | ||
// HTML for dropdown button (name of active font and dropdown arrow) | ||
this.dropdownButton = document.createElement('a'); | ||
this.dropdownButton.classList.add('dropdown-button'); | ||
this.dropdownButton.role = 'button'; | ||
this.dropdownButton.tabIndex = 0; | ||
this.dropdownButton.onclick = function () { | ||
return _this.toggleExpanded(); | ||
}; | ||
this.dropdownButton.onkeypress = function () { | ||
return _this.toggleExpanded(); | ||
}; | ||
// HTML for font list entries | ||
_this.ul.onscroll = function () { | ||
return _this.onScroll(); | ||
}; // download font previews on scroll | ||
this.dropdownFont = document.createElement('p'); | ||
this.dropdownFont.innerHTML = this.fontHandler.activeFont.family; | ||
var _loop = function _loop(i) { | ||
var li = document.createElement('li'); | ||
var a = document.createElement('a'); | ||
this.dropdownButton.append(this.dropdownFont); | ||
fontPickerDiv.appendChild(this.dropdownButton); | ||
var dropdownIcon = document.createElement('p'); | ||
dropdownIcon.classList.add('dropdown-icon', 'loading'); | ||
this.dropdownButton.append(dropdownIcon); | ||
// write font name in the corresponding font, set onclick listener | ||
a.innerHTML = _this.fontHandler.fonts[i].family; | ||
a.classList.add('font-' + _this.fontHandler.fonts[i].family.replace(/\s+/g, '-').toLowerCase()); | ||
a.role = 'button'; | ||
a.tabIndex = 0; | ||
a.onclick = function () { | ||
_this.toggleExpanded(); // collapse font list | ||
_this.selectFont(i); // make font with index i active | ||
}; | ||
a.onkeypress = function () { | ||
_this.toggleExpanded(); // collapse font list | ||
_this.selectFont(i); // make font with index i active | ||
}; | ||
li.appendChild(a); | ||
// HTML for font list | ||
this.ul = document.createElement('ul'); | ||
// if active font: highlight it and save reference | ||
if (_this.fontHandler.fonts[i].family === _this.fontHandler.activeFont.family) { | ||
a.classList.add('active-font'); | ||
_this.activeFontA = a; | ||
} | ||
// fetch font list, display dropdown arrow if successful | ||
this.fontHandler.init().then(function () { | ||
dropdownIcon.classList.remove('loading'); | ||
dropdownIcon.classList.add('finished'); | ||
// HTML for font list entries | ||
_this.ul.onscroll = function () { | ||
return _this.onScroll(); | ||
}; // download font previews on scroll | ||
var _loop = function _loop(i) { | ||
var li = document.createElement('li'); | ||
var a = document.createElement('a'); | ||
// write font name in the corresponding font, set onclick listener | ||
a.innerHTML = _this.fontHandler.fonts[i].family; | ||
a.classList.add('font-' + _this.fontHandler.fonts[i].family.replace(/\s+/g, '-').toLowerCase()); | ||
a.role = 'button'; | ||
a.tabIndex = 0; | ||
a.onclick = function () { | ||
_this.toggleExpanded(); // collapse font list | ||
_this.selectFont(i); // make font with index i active | ||
_this.ul.appendChild(li); | ||
}; | ||
a.onkeypress = function () { | ||
_this.toggleExpanded(); // collapse font list | ||
_this.selectFont(i); // make font with index i active | ||
}; | ||
li.appendChild(a); | ||
// if active font: highlight it and save reference | ||
if (_this.fontHandler.fonts[i].family === _this.fontHandler.activeFont.family) { | ||
a.classList.add('active-font'); | ||
_this.activeFontA = a; | ||
for (var i = 0; i < _this.fontHandler.fonts.length; i += 1) { | ||
_loop(i); | ||
} | ||
fontPickerDiv.appendChild(_this.ul); | ||
}).catch(function (err) { | ||
dropdownIcon.classList.remove('loading'); | ||
dropdownIcon.classList.add('error'); | ||
var errMessage = 'Error trying to fetch the list of available fonts'; | ||
console.error(errMessage); | ||
console.error(err); | ||
fontPickerDiv.title = errMessage; | ||
}); | ||
} | ||
_this.ul.appendChild(li); | ||
}; | ||
/** | ||
* Return the object of the currently selected font | ||
*/ | ||
for (var i = 0; i < _this.fontHandler.fonts.length; i += 1) { | ||
_loop(i); | ||
} | ||
fontPickerDiv.appendChild(_this.ul); | ||
}).catch(function (err) { | ||
dropdownIcon.classList.remove('loading'); | ||
dropdownIcon.classList.add('error'); | ||
var errMessage = 'Error trying to fetch the list of available fonts'; | ||
console.error(errMessage); | ||
console.error(err); | ||
fontPickerDiv.title = errMessage; | ||
}); | ||
} | ||
}, { | ||
key: 'getActiveFont', | ||
value: function getActiveFont() { | ||
return this.fontHandler.activeFont; | ||
} | ||
/** | ||
* Return the object of the currently selected font | ||
*/ | ||
/** | ||
* EventListener for closing the font picker when clicking anywhere outside it | ||
*/ | ||
}, { | ||
key: 'getActiveFont', | ||
value: function getActiveFont() { | ||
return this.fontHandler.activeFont; | ||
} | ||
}, { | ||
key: 'closeEventListener', | ||
value: function closeEventListener(e) { | ||
var targetElement = e.target; // clicked element | ||
/** | ||
* EventListener for closing the font picker when clicking anywhere outside it | ||
*/ | ||
do { | ||
if (targetElement === document.getElementById('font-picker' + this.name)) { | ||
// click inside font picker | ||
return; | ||
} | ||
// move up the DOM | ||
targetElement = targetElement.parentNode; | ||
} while (targetElement); | ||
}, { | ||
key: 'closeEventListener', | ||
value: function closeEventListener(e) { | ||
var targetElement = e.target; // clicked element | ||
// click outside font picker | ||
this.toggleExpanded(); | ||
} | ||
do { | ||
if (targetElement === document.getElementById('font-picker' + this.name)) { | ||
// click inside font picker | ||
return; | ||
} | ||
// move up the DOM | ||
targetElement = targetElement.parentNode; | ||
} while (targetElement); | ||
/** | ||
* Download the font previews for all visible font entries and the five after them | ||
*/ | ||
// click outside font picker | ||
this.toggleExpanded(); | ||
} | ||
}, { | ||
key: 'onScroll', | ||
value: function onScroll() { | ||
var elementHeight = this.ul.scrollHeight / this.fontHandler.fonts.length; | ||
var downloadIndex = Math.ceil((this.ul.scrollTop + this.ul.clientHeight) / elementHeight); | ||
this.fontHandler.downloadPreviews(downloadIndex + 5); | ||
} | ||
/** | ||
* Download the font previews for all visible font entries and the five after them | ||
*/ | ||
/** | ||
* Set the font with the given font list index as the active one and highlight it in the list | ||
*/ | ||
}, { | ||
key: 'onScroll', | ||
value: function onScroll() { | ||
var elementHeight = this.ul.scrollHeight / this.fontHandler.fonts.length; | ||
var downloadIndex = Math.ceil((this.ul.scrollTop + this.ul.clientHeight) / elementHeight); | ||
this.fontHandler.downloadPreviews(downloadIndex + 5); | ||
} | ||
}, { | ||
key: 'selectFont', | ||
value: function selectFont(index) { | ||
// change font | ||
this.fontHandler.changeActiveFont(index); | ||
/** | ||
* Set the font with the given font list index as the active one and highlight it in the list | ||
*/ | ||
// write new font name in dropdown button | ||
this.dropdownFont.innerHTML = this.fontHandler.activeFont.family; | ||
}, { | ||
key: 'selectFont', | ||
value: function selectFont(index) { | ||
// change font | ||
this.fontHandler.changeActiveFont(index); | ||
// highlight new active font | ||
this.activeFontA.classList.remove('active-font'); | ||
this.activeFontA = this.ul.getElementsByTagName('li')[index].firstChild; | ||
this.activeFontA.classList.add('active-font'); | ||
} | ||
// write new font name in dropdown button | ||
this.dropdownFont.innerHTML = this.fontHandler.activeFont.family; | ||
/** | ||
* Expand/collapse the picker's font list | ||
*/ | ||
// highlight new active font | ||
this.activeFontA.classList.remove('active-font'); | ||
this.activeFontA = this.ul.getElementsByTagName('li')[index].firstChild; | ||
this.activeFontA.classList.add('active-font'); | ||
} | ||
}, { | ||
key: 'toggleExpanded', | ||
value: function toggleExpanded() { | ||
if (this.expanded) { | ||
this.expanded = false; | ||
this.dropdownButton.classList.remove('expanded'); | ||
this.ul.classList.remove('expanded'); | ||
document.removeEventListener('click', this.closeEventListener); | ||
} else { | ||
this.expanded = true; | ||
this.dropdownButton.classList.add('expanded'); | ||
this.ul.classList.add('expanded'); | ||
document.addEventListener('click', this.closeEventListener); | ||
} | ||
} | ||
}]); | ||
return FontPicker; | ||
}(); | ||
/** | ||
* Expand/collapse the picker's font list | ||
*/ | ||
}, { | ||
key: 'toggleExpanded', | ||
value: function toggleExpanded() { | ||
if (this.expanded) { | ||
this.expanded = false; | ||
this.dropdownButton.classList.remove('expanded'); | ||
this.ul.classList.remove('expanded'); | ||
document.removeEventListener('click', this.closeEventListener); | ||
} else { | ||
this.expanded = true; | ||
this.dropdownButton.classList.add('expanded'); | ||
this.ul.classList.add('expanded'); | ||
document.addEventListener('click', this.closeEventListener); | ||
} | ||
} | ||
}]); | ||
return FontPicker; | ||
}(); | ||
return FontPicker; | ||
}))); |
{ | ||
"name": "font-picker", | ||
"version": "1.2.1", | ||
"version": "1.3.0", | ||
"description": "Font picker component for previewing, selecting, and downloading Google Fonts", | ||
@@ -19,3 +19,3 @@ "keywords": [ | ||
"build": "rollup -c", | ||
"lint": "eslint --ext .js src", | ||
"lint": "eslint .", | ||
"precommit": "npm run lint", | ||
@@ -28,11 +28,11 @@ "prepush": "npm run lint" | ||
"babel-preset-env": "^1.6.1", | ||
"eslint": "^4.15.0", | ||
"eslint": "^4.19.1", | ||
"eslint-config-airbnb-base": "^12.1.0", | ||
"eslint-plugin-import": "^2.8.0", | ||
"eslint-plugin-import": "^2.9.0", | ||
"husky": "^0.14.3", | ||
"node-sass": "^4.7.2", | ||
"postcss": "^6.0.16", | ||
"rollup": "^0.54.0", | ||
"node-sass": "^4.8.3", | ||
"postcss": "^6.0.21", | ||
"rollup": "^0.57.1", | ||
"rollup-plugin-babel": "^3.0.3", | ||
"rollup-plugin-postcss": "^1.2.5" | ||
"rollup-plugin-postcss": "^1.4.0" | ||
}, | ||
@@ -39,0 +39,0 @@ "files": [ |
@@ -17,3 +17,3 @@ # Font Picker | ||
<p align="center"> | ||
<img src=".github/demo.gif" width=800 alt="Demo"> | ||
<img src=".github/demo.gif" width=700 alt="Demo"> | ||
</p> | ||
@@ -114,2 +114,2 @@ | ||
* `npm start` to generate the library bundle using [Rollup](https://github.com/rollup/rollup) (in the `lib` directory) | ||
* See the font picker in action by opening the [`demo/index.html`](demo/index.html) file | ||
* See the font picker in action by opening the [`demo/index.html`](demo/index.html) file |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
32576
593
114