Skip to content

Instantly share code, notes, and snippets.

@timgreen
Created April 18, 2009 21:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save timgreen/97788 to your computer and use it in GitHub Desktop.
Save timgreen/97788 to your computer and use it in GitHub Desktop.
Ubiquity feed - dictcn
Cache = function(namespace) {
this.namespace = namespace;
this.store = Application.storage;
};
Cache.prototype = {
_: function(key) {
return this.namespace + '-' + key;
},
has: function(key) {
return this.store.has(this._(key));
},
getJson: function(key, defaultValue) {
return Utils.decodeJson(this.store.get(this._(key),
defaultValue && Utils.encodeJson(defaultValue)));
},
setJson: function(key, value) {
this.store.set(this._(key), Utils.encodeJson(value));
},
get: function(key, defaultValue) {
return this.store.get(this._(key), defaultValue);
},
set: function(key, value) {
this.store.set(this._(key), value);
}
};
CmdUtils.CreateCommand({
name: 'dictcn',
synonyms: ['dcn'],
description: 'Translates word via Dict.cn.',
icon: 'http://dict.cn/favicon.ico',
homepage: 'http://gist.github.com/97788',
help: 'Get translate from <a href="dict.cn">Dict.cn</a>. Both English to Chinese or Chinese to English.',
author: {
name: 'Tim Green',
email: 'iamtimgreen+ubiquity@gmail.com'
},
license: 'MPL',
takes: {"word to translate": noun_arb_text},
cache: new Cache('ubiquity-dictcn'),
execute: function() {
// Simply return, works will be done in preview.
return;
},
previewDelay: 200, // 200ms.
preview: function(pblock, directObj) {
this.translate(pblock, directObj.text);
},
translate: function(pblock, text) {
if (!text) {
pblock.innerHTML = 'Select or type the word need to translate.';
} else if (text.match(/\w+/) && text.length < 3) {
pblock.innerHTML = 'Need at lest 3 english chars.';
} else {
var urlbase = 'http://api.dict.cn/ws.php?utf8=true&q=';
pblock.innerHTML = 'Translating <strong style="color:#090;font-size:18px">' + Utils.escapeHtml(text) + '</strong> ...';
this.cachedPreviewGet(pblock, urlbase + encodeURI(text), function(json, cached) {
json['cached'] = cached;
var template = [
'<style>',
'#dictcn {',
'font-family: Verdana,Geneva,Arial,Helvetica,sans-serif;',
'font-size: 12px;',
'}',
'.key {',
'color: #090;',
'font-weight: bold;',
'font-size: 18px;',
'margin-right: 5px;',
'text-decoration: none;',
'}',
'.pron, .text {',
'font-size: 16px;',
'}',
'.pron {',
'color: #969;',
'font-family: "lucida sans unicode",sans-serif;',
'margin-right: 5px;',
'}',
'.def {',
'font-size: 14px;',
'font-weight: bold;',
'}',
'.sents h3, .rels h3, .suggs h3 {',
'background: transparent url(http://dict.cn/imgs/dotline_h.gif) repeat-x scroll center bottom;',
'font-size: 14px;',
'line-height: 26px;',
'}',
'.rels span {',
'font-size: 13px;',
'margin-right: 5px;',
'}',
'.rel {',
'color: #369;',
'text-decoration: none;',
'}',
'.cachemark {',
'float: right;',
'font-weight: bold;',
'color: grey;',
'}',
'</style>'
];
if (!json.key) {
// Not found.
CmdUtils.previewGet(pblock, urlbase + '[' + encodeURI(text) + ']', function(data2) {
var xml2 = jQuery(data2).find('dict');
template.push(
'<div id="dictcn">',
'<div>',
'{if cached}<span class="cachemark">|Cached ${cached}|</span>{/if}',
'<a class="key" href="http://dict.cn/${key}">${key}</a>',
'<strong class="text">not found</strong>.',
'</div>',
'{if suggs.length}<div class="suggs">',
'<h3>您要查找的是不是:</h3>',
'<ul>',
'{for sugg in suggs}',
'{if !isNaN(parseInt(sugg_index, 10))}',
'<li>',
'<a class="rel" href="http://dict.cn/${sugg}">${sugg}</a>',
'</li>',
'{/if}',
'{/for}',
'</ul>',
'</div>{/if}',
'</div>');
var suggs = xml2.children('sugg').map(function() {
return jQuery(this).text();
});
pblock.innerHTML = CmdUtils.renderTemplate(template.join(''), {
key: text,
suggs: suggs,
cached: false
});
});
} else {
template.push(
'<div id="dictcn">',
'<div>',
'{if cached}<span class="cachemark">|Cached ${cached}|</span>{/if}',
'<a class="key" href="http://dict.cn/${key}">${key}</a>',
'{if pron}<span class="pron">[${pron}]</span>{/if}',
'{if audio}',
'(<embed src="http://dict.cn/img/audio.swf"',
'loop="false"',
'menu="false"',
'quality="high"',
'wmode="transparent"',
'flashvars="audio=${audio}"',
'type="application/x-shockwave-flash"',
'pluginspage="http://www.macromedia.com/go/getflashplayer"',
'align="absmiddle"',
'height="13"',
'width="13" />)',
// FIXME(timgreen): No sound when mouseover or click.
'{/if}',
'</div>',
'<div class="def">',
"${def}",
'</div>',
'{if rels.length}<div class="rels">',
'<h3>关联词条:</h3>',
'{for rel in rels}',
'{if !isNaN(parseInt(rel_index, 10))}',
'<span>&lt;<a href="http://dict.cn/${rel}" class="rel">${rel}</a>&gt;</span>',
'{/if}',
'{/for}',
'</div>{/if}',
'{if sents.length}<div class="sents">',
'<h3>例句与用法:</h3>',
'<ol>',
'{for sent in sents}',
'{if !isNaN(parseInt(sent_index, 10))}',
'<li>',
'${sent.orig}',
'<div>${sent.trans}</div>',
'</li>',
'{/if}',
'{/for}',
'</ol>',
'</div>{/if}',
'</div>');
pblock.innerHTML = CmdUtils.renderTemplate(template.join(''), json);
// TODO(timgreen): enable translate related word by click.
// Currently ubiquity eat all events.
}
}, 'xml');
}
},
xml2json: function(data) {
var xml = jQuery(data).find('dict');
function getText(key) {
return xml.children(key).text();
}
var audio = getText('audio').replace(/^.*=/, '');
var def = getText('def').replace(/\n/g, '<br/>');
var sents = [];
xml.children('sent').each(function() {
sents.push({
orig: jQuery('orig', this).text(),
trans: jQuery('trans', this).text()
});
});
var rels = [];
xml.children('rel').each(function() {
rels.push(jQuery(this).text());
});
return {
key: getText('key'),
pron: getText('pron'),
audio: audio,
def: def,
sents: sents,
rels: rels
};
},
/**
* Callback function should defined as func(data, cached).
*/
cachedPreviewGet: function(pblock, url, func) {
var self = this;
var cachedUrls = this.cache.getJson('cachedUrls', {});
var order = this.cache.getJson('order', []);
var idx = cachedUrls[url];
if (idx) {
// Re put this url at the end.
order.splice(order.indexOf(url), 1);
order.push(url);
func(this.cache.getJson('cache' + idx), '' + idx + '-' + order.length);
this.cache.setJson('order', order);
} else {
CmdUtils.previewGet(pblock, url, function(data) {
if (order.length >= self.MAX_CACHE) {
var oldUrl = order.shift();
idx = cachedUrls[oldUrl];
delete cachedUrls[oldUrl];
} else {
idx = order.length + 1;
}
order.push(url);
cachedUrls[url] = idx;
var json = self.xml2json(data);
func(json, false);
self.cache.setJson('cache' + idx, json);
self.cache.setJson('order', order);
self.cache.setJson('cachedUrls', cachedUrls);
});
}
},
MAX_CACHE: 10
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment