diff --git a/README.md b/README.md index 84cd00c..0987cd8 100755 --- a/README.md +++ b/README.md @@ -15,6 +15,17 @@ To use Typo in a standard web application you need to pass a settings object tha var dictionary = new Typo("en_US", false, false, { dictionaryPath: "typo/dictionaries" }), ``` +To load custom dic and aff files, and you can also provide a callback progress: + +```javascript +var dictionary = new Typo("en_US", affData, wordsData, { + progressCallback: function (objectType, i, total) { + var pct = parseInt((10000 * i) / total, 10) / 100; + console.log('Processing ' + objectType + ': ' + pct + '%...'); + } +}), +``` + If using in node.js, load it like so: ```javascript diff --git a/tests/general.js b/tests/general.js index fe3a763..d4bc0c3 100644 --- a/tests/general.js +++ b/tests/general.js @@ -46,6 +46,25 @@ function run() { var dict = new Typo("en_US", affData, wordData); checkLoadedDict(dict); }); + + test("Progress callbacks are being called", function() { + var dicCb = false; + var affCb = false; + var affData = empty_dict._readFile(chrome.extension.getURL("../typo/dictionaries/en_US/en_US.aff")); + var wordData = empty_dict._readFile(chrome.extension.getURL("../typo/dictionaries/en_US/en_US.dic")); + var dict = new Typo("en_US", affData, wordData, { + progressCallback: function (obType, i, total) { + if (obType === 'dic') { + dicCb = true; + } else if (obType === 'aff') { + affCb = true; + } + } + }); + checkLoadedDict(dict); + ok(dicCb); + ok(affCb); + }); test("Synchronous load of dictionary data", function() { var dict = new Typo("en_US"); diff --git a/typo/typo.js b/typo/typo.js index d66353c..79b53d6 100644 --- a/typo/typo.js +++ b/typo/typo.js @@ -40,6 +40,8 @@ var Typo; * {Function} [loadedCallback]: Called when both affData and wordsData * have been loaded. Only used if asyncLoad is set to true. The parameter * is the instantiated Typo object. + * {Function} [progressCallback]: Called when processing .aff and .dic files + * signature: progressCallback(opType, i, total), where opType = 'dic' or 'aff' * * @returns {Typo} A Typo object. */ @@ -57,7 +59,7 @@ Typo = function (dictionary, affData, wordsData, settings) { this.replacementTable = []; - this.flags = settings.flags || {}; + this.flags = settings.flags || {}; this.memoized = {}; @@ -75,7 +77,7 @@ Typo = function (dictionary, affData, wordsData, settings) { // If the data is preloaded, just setup the Typo object. if (affData && wordsData) { - setup(); + setup(settings.progressCallback); } // Loading data for Chrome extentions. else if (typeof window !== 'undefined' && 'chrome' in window && 'extension' in window.chrome && 'getURL' in window.chrome.extension) { @@ -86,8 +88,8 @@ Typo = function (dictionary, affData, wordsData, settings) { path = "typo/dictionaries"; } - if (!affData) readDataFile(chrome.extension.getURL(path + "/" + dictionary + "/" + dictionary + ".aff"), setAffData); - if (!wordsData) readDataFile(chrome.extension.getURL(path + "/" + dictionary + "/" + dictionary + ".dic"), setWordsData); + if (!affData) readDataFile(chrome.extension.getURL(path + "/" + dictionary + "/" + dictionary + ".aff"), setAffData, settings.progressCallback); + if (!wordsData) readDataFile(chrome.extension.getURL(path + "/" + dictionary + "/" + dictionary + ".dic"), setWordsData, settings.progressCallback); } else { if (settings.dictionaryPath) { @@ -100,42 +102,42 @@ Typo = function (dictionary, affData, wordsData, settings) { path = './dictionaries'; } - if (!affData) readDataFile(path + "/" + dictionary + "/" + dictionary + ".aff", setAffData); - if (!wordsData) readDataFile(path + "/" + dictionary + "/" + dictionary + ".dic", setWordsData); + if (!affData) readDataFile(path + "/" + dictionary + "/" + dictionary + ".aff", setAffData, settings.progressCallback); + if (!wordsData) readDataFile(path + "/" + dictionary + "/" + dictionary + ".dic", setWordsData, settings.progressCallback); } } - function readDataFile(url, setFunc) { + function readDataFile(url, setFunc, progressCallback) { var response = self._readFile(url, null, settings.asyncLoad); if (settings.asyncLoad) { response.then(function(data) { - setFunc(data); + setFunc(data, progressCallback); }); } else { - setFunc(response); + setFunc(response, progressCallback); } } - function setAffData(data) { + function setAffData(data, progressCallback) { affData = data; if (wordsData) { - setup(); + setup(progressCallback); } } - function setWordsData(data) { + function setWordsData(data, progressCallback) { wordsData = data; if (affData) { - setup(); + setup(progressCallback); } } - function setup() { - self.rules = self._parseAFF(affData); + function setup(progressCallback) { + self.rules = self._parseAFF(affData, progressCallback); // Save the rule codes that are used in compound rules. self.compoundRuleCodes = {}; @@ -154,7 +156,7 @@ Typo = function (dictionary, affData, wordsData, settings) { self.compoundRuleCodes[self.flags.ONLYINCOMPOUND] = []; } - self.dictionaryTable = self._parseDIC(wordsData); + self.dictionaryTable = self._parseDIC(wordsData, progressCallback); // Get rid of any codes from the compound rule codes that are never used // (or that were special regex characters). Not especially necessary... @@ -289,7 +291,7 @@ Typo.prototype = { * @returns object The rules from the file. */ - _parseAFF : function (data) { + _parseAFF : function (data, progressCallback) { var rules = {}; var line, subline, numEntries, lineParts; @@ -301,6 +303,9 @@ Typo.prototype = { var lines = data.split("\n"); for (i = 0, _len = lines.length; i < _len; i++) { + if (progressCallback) { + progressCallback('aff', i, _len); + } line = lines[i]; var definitionParts = line.split(/\s+/); @@ -427,7 +432,7 @@ Typo.prototype = { * word forms from the dictionary. */ - _parseDIC : function (data) { + _parseDIC : function (data, progressCallback) { data = this._removeDicComments(data); var lines = data.split("\n"); @@ -450,13 +455,16 @@ Typo.prototype = { // The first line is the number of words in the dictionary. for (var i = 1, _len = lines.length; i < _len; i++) { + if (progressCallback) { + progressCallback('dic', i, _len); + } var line = lines[i]; if (!line) { // Ignore empty lines. continue; } - + var parts = line.split("/", 2); var word = parts[0];