Path: blob/trunk/third_party/closure/goog/i18n/uchar/remotenamefetcher.js
2868 views
// Copyright 2012 The Closure Library Authors. All Rights Reserved.1//2// Licensed under the Apache License, Version 2.0 (the "License");3// you may not use this file except in compliance with the License.4// You may obtain a copy of the License at5//6// http://www.apache.org/licenses/LICENSE-2.07//8// Unless required by applicable law or agreed to in writing, software9// distributed under the License is distributed on an "AS-IS" BASIS,10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.11// See the License for the specific language governing permissions and12// limitations under the License.1314/**15* @fileoverview Object which fetches Unicode codepoint names from a remote data16* source. This data source should accept two parameters:17* <ol>18* <li>c - the list of codepoints in hexadecimal format19* <li>p - the name property20* </ol>21* and return a JSON object representation of the result.22* For example, calling this data source with the following URL:23* http://datasource?c=50,ff,102bd&p=name24* Should return a JSON object which looks like this:25* <pre>26* {"50":{"name":"LATIN CAPITAL LETTER P"},27* "ff":{"name":"LATIN SMALL LETTER Y WITH DIAERESIS"},28* "102bd":{"name":"CARIAN LETTER K2"}}29* </pre>.30*/3132goog.provide('goog.i18n.uChar.RemoteNameFetcher');3334goog.require('goog.Disposable');35goog.require('goog.Uri');36goog.require('goog.events');37goog.require('goog.i18n.uChar');38goog.require('goog.i18n.uChar.NameFetcher');39goog.require('goog.log');40goog.require('goog.net.EventType');41goog.require('goog.net.XhrIo');42goog.require('goog.structs.Map');43444546/**47* Builds the RemoteNameFetcher object. This object retrieves codepoint names48* from a remote data source.49*50* @param {string} dataSourceUri URI to the data source.51* @constructor52* @implements {goog.i18n.uChar.NameFetcher}53* @extends {goog.Disposable}54* @final55*/56goog.i18n.uChar.RemoteNameFetcher = function(dataSourceUri) {57goog.i18n.uChar.RemoteNameFetcher.base(this, 'constructor');5859/**60* XHRIo object for prefetch() asynchronous calls.61*62* @type {!goog.net.XhrIo}63* @private64*/65this.prefetchXhrIo_ = new goog.net.XhrIo();6667/**68* XHRIo object for getName() asynchronous calls.69*70* @type {!goog.net.XhrIo}71* @private72*/73this.getNameXhrIo_ = new goog.net.XhrIo();7475/**76* URI to the data.77*78* @type {string}79* @private80*/81this.dataSourceUri_ = dataSourceUri;8283/**84* A cache of all the collected names from the server.85*86* @type {!goog.structs.Map}87* @private88*/89this.charNames_ = new goog.structs.Map();90};91goog.inherits(goog.i18n.uChar.RemoteNameFetcher, goog.Disposable);929394/**95* Key to the listener on XHR for prefetch(). Used to clear previous listeners.96*97* @type {goog.events.Key}98* @private99*/100goog.i18n.uChar.RemoteNameFetcher.prototype.prefetchLastListenerKey_;101102103/**104* Key to the listener on XHR for getName(). Used to clear previous listeners.105*106* @type {goog.events.Key}107* @private108*/109goog.i18n.uChar.RemoteNameFetcher.prototype.getNameLastListenerKey_;110111112/**113* A reference to the RemoteNameFetcher logger.114*115* @type {goog.log.Logger}116* @private117*/118goog.i18n.uChar.RemoteNameFetcher.logger_ =119goog.log.getLogger('goog.i18n.uChar.RemoteNameFetcher');120121122123124/** @override */125goog.i18n.uChar.RemoteNameFetcher.prototype.disposeInternal = function() {126goog.i18n.uChar.RemoteNameFetcher.base(this, 'disposeInternal');127this.prefetchXhrIo_.dispose();128this.getNameXhrIo_.dispose();129};130131132/** @override */133goog.i18n.uChar.RemoteNameFetcher.prototype.prefetch = function(characters) {134// Abort the current request if there is one135if (this.prefetchXhrIo_.isActive()) {136goog.log.info(137goog.i18n.uChar.RemoteNameFetcher.logger_,138'Aborted previous prefetch() call for new incoming request');139this.prefetchXhrIo_.abort();140}141if (this.prefetchLastListenerKey_) {142goog.events.unlistenByKey(this.prefetchLastListenerKey_);143}144145// Set up new listener146var preFetchCallback = goog.bind(this.prefetchCallback_, this);147this.prefetchLastListenerKey_ = goog.events.listenOnce(148this.prefetchXhrIo_, goog.net.EventType.COMPLETE, preFetchCallback);149150this.fetch_(151goog.i18n.uChar.RemoteNameFetcher.RequestType_.BASE_88, characters,152this.prefetchXhrIo_);153};154155156/**157* Callback on completion of the prefetch operation.158*159* @private160*/161goog.i18n.uChar.RemoteNameFetcher.prototype.prefetchCallback_ = function() {162this.processResponse_(this.prefetchXhrIo_);163};164165166/** @override */167goog.i18n.uChar.RemoteNameFetcher.prototype.getName = function(168character, callback) {169var codepoint = goog.i18n.uChar.toCharCode(character).toString(16);170171if (this.charNames_.containsKey(codepoint)) {172var name = /** @type {string} */ (this.charNames_.get(codepoint));173callback(name);174return;175}176177// Abort the current request if there is one178if (this.getNameXhrIo_.isActive()) {179goog.log.info(180goog.i18n.uChar.RemoteNameFetcher.logger_,181'Aborted previous getName() call for new incoming request');182this.getNameXhrIo_.abort();183}184if (this.getNameLastListenerKey_) {185goog.events.unlistenByKey(this.getNameLastListenerKey_);186}187188// Set up new listener189var getNameCallback =190goog.bind(this.getNameCallback_, this, codepoint, callback);191this.getNameLastListenerKey_ = goog.events.listenOnce(192this.getNameXhrIo_, goog.net.EventType.COMPLETE, getNameCallback);193194this.fetch_(195goog.i18n.uChar.RemoteNameFetcher.RequestType_.CODEPOINT, codepoint,196this.getNameXhrIo_);197};198199200/**201* Callback on completion of the getName operation.202*203* @param {string} codepoint The codepoint in hexadecimal format.204* @param {function(?string)} callback The callback function called when the205* name retrieval is complete, contains a single string parameter with the206* codepoint name, this parameter will be null if the character name is not207* defined.208* @private209*/210goog.i18n.uChar.RemoteNameFetcher.prototype.getNameCallback_ = function(211codepoint, callback) {212this.processResponse_(this.getNameXhrIo_);213var name = /** @type {?string} */ (this.charNames_.get(codepoint, null));214callback(name);215};216217218/**219* Process the response received from the server and store results in the cache.220*221* @param {!goog.net.XhrIo} xhrIo The XhrIo object used to make the request.222* @private223*/224goog.i18n.uChar.RemoteNameFetcher.prototype.processResponse_ = function(xhrIo) {225if (!xhrIo.isSuccess()) {226goog.log.error(227goog.i18n.uChar.RemoteNameFetcher.logger_,228'Problem with data source: ' + xhrIo.getLastError());229return;230}231var result = xhrIo.getResponseJson();232for (var codepoint in result) {233if (result[codepoint].hasOwnProperty('name')) {234this.charNames_.set(codepoint, result[codepoint]['name']);235}236}237};238239240/**241* Enum for the different request types.242*243* @enum {string}244* @private245*/246goog.i18n.uChar.RemoteNameFetcher.RequestType_ = {247248/**249* Request type that uses a base 88 string containing a set of codepoints to250* be fetched from the server (see goog.i18n.charpickerdata for more251* information on b88).252*/253BASE_88: 'b88',254255/**256* Request type that uses a a string of comma separated codepoint values.257*/258CODEPOINT: 'c'259};260261262/**263* Fetches a set of codepoint names from the data source.264*265* @param {!goog.i18n.uChar.RemoteNameFetcher.RequestType_} requestType The266* request type of the operation. This parameter specifies how the server is267* called to fetch a particular set of codepoints.268* @param {string} requestInput The input to the request, this is the value that269* is passed onto the server to complete the request.270* @param {!goog.net.XhrIo} xhrIo The XHRIo object to execute the server call.271* @private272*/273goog.i18n.uChar.RemoteNameFetcher.prototype.fetch_ = function(274requestType, requestInput, xhrIo) {275var url = new goog.Uri(this.dataSourceUri_);276url.setParameterValue(requestType, requestInput);277url.setParameterValue('p', 'name');278goog.log.info(279goog.i18n.uChar.RemoteNameFetcher.logger_, 'Request: ' + url.toString());280xhrIo.send(url);281};282283284/** @override */285goog.i18n.uChar.RemoteNameFetcher.prototype.isNameAvailable = function(286character) {287return true;288};289290291