Created
April 18, 2009 21:20
-
-
Save timgreen/97788 to your computer and use it in GitHub Desktop.
Ubiquity feed - dictcn
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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><<a href="http://dict.cn/${rel}" class="rel">${rel}</a>></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