Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Initial commit

  • Loading branch information...
commit acbd274a09638c54e62a2c968774355b5f732c62 0 parents
Timothy Guan-tin Chien authored
3  .gitignore
@@ -0,0 +1,3 @@
+wordcloud.min.js
+wordfreq.min.js
+wordfreq.worker.min.js
BIN  beachball.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
164 en/index.html
@@ -0,0 +1,164 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset=UTF-8>
+<title>HTML5 Word Cloud: Text Analyzer</title>
+<link rel="stylesheet" type="text/css" href="../wordcloud.css" />
+</head>
+<body>
+<canvas id="canvas" class="toggleUI"></canvas>
+<div id="loading" class="center_msg">
+ <p>Loading ...</p>
+</div>
+<div id="error" class="error toggleUI center_msg">
+ <p>&nbsp;</p>
+ <a href="#" class="start">Try Again</a>
+</div>
+<div id="too_slow" class="error toggleUI center_msg">
+ <p>Your browser is too slow. Execute the analyzer could cause it to hang. Please switch to other browser (This happened to some Firefox installations.)</p>
+</div>
+<div id="not_support" class="error toggleUI center_msg">
+ <p>Some of the required functionality are missing from your browser.</p>
+ <p>Please upgrade, or switch to HTML5-capable browsers:</p>
+ <ul>
+ <li><a href="http://mozilla.com/firefox/" target="_blank">Firefox</a></li>
+ <li><a href="http://www.apple.com/safari/" target="_blank">Safari</a></li>
+ <li><a href="http://www.google.com/chrome/" target="_blank">Chrome</a></li>
+ <li><a href="http://www.opera.com/" target="_blank">Opera</a></li>
+ </ul>
+</div>
+<noscript>
+<div class="center_msg">
+ <p>Please enable JavaScript.</p>
+</div>
+</noscript>
+<p id="title"></p>
+<a id="start" href="#" class="toggleUI start center_btn">Word Clouds - Click to Start</a>
+<a id="ready" href="#" class="toggleUI ready center_btn">Ready</a>
+<div id="controls" class="toggleUI left_tool">
+ <ul>
+ <li><a href="#" class="changetheme"><span class="famfamfam_sprite color_wheel"></span>Change color scheme</a></li>
+ <li><a href="#" class="larger"><span class="famfamfam_sprite comment"></span>Larger Text</a></li>
+ <li><a href="#" class="smaller"><span class="famfamfam_sprite comments"></span>Smaller Text</a></li>
+ <!-- disable to novice user
+ <li><a href="#" class="thicker"><span class="famfamfam_sprite arrow_out"></span>Bigger Gap</a></li>
+ <li><a href="#" class="thiner"><span class="famfamfam_sprite arrow_in"></span>Smaller Gap</a></li>
+ -->
+ <li><a href="#" class="ready"><span class="famfamfam_sprite arrow_refresh"></span>Regenerate</a></li>
+ <li><a href="#" class="save"><span class="famfamfam_sprite disk"></span>Save</a></li>
+ </ul>
+</div>
+<div id="help" class="left_tool">
+ <ul>
+ <li><a href="#" class="start"><span class="famfamfam_sprite arrow_undo"></span>Reset</a></li>
+ <li><a href="#" class="help"><span class="famfamfam_sprite help"></span>About</a></li>
+ </ul>
+</div>
+<div id="language" class="left_tool">
+ <ul>
+ <li><strong>English</strong></li>
+ <li><a href="../zh/">正體中文</a></li>
+ </ul>
+</div>
+<div id="source_panel" class="toggleUI panel">
+ <h2>Text Source for Word Clouds</h2>
+ <form id="source_panel_form" action="#" method="post">
+ <p class="menu panel_left">
+ <label class="generic"><span class="famfamfam_sprite award_star_bronze_1"></span><input type="radio" name="source" value="demo" checked /> Examples</label>
+ <label class="generic"><span class="famfamfam_sprite feed"></span><input type="radio" name="source" value="feed" /> RSS Feed</label>
+ <!--<label class="generic"><span class="famfamfam_sprite page_world"></span><input type="radio" name="source" value="html" /> Webpages</label>-->
+ <label class="generic"><span class="famfamfam_sprite disk"></span><input type="radio" name="source" value="file" /> Local file</label>
+ <!--<label><input type="radio" name="source" value="wiki" /> Wikipedia</label>-->
+ <label><input type="radio" name="source" value="blog:blogger" /> Blogger</label>
+ <label><input type="radio" name="source" value="blog:twitter"/> Twitter</label>
+ </p>
+ <hr />
+ <div id="demo_entry" class="entry">
+ <p>Examples</p>
+ <p class="menu">
+ <label><input type="radio" name="demo" value="feed:http://www.nytimes.com/services/xml/rss/nyt/GlobalHome.xml" checked /> New York Times (Global Edition)</label>
+ <label><input type="radio" name="demo" value="feed:http://www.nytimes.com/services/xml/rss/nyt/HomePage.xml" /> New York Times (U.S.)</label>
+ <label><input type="radio" name="demo" value="feed:http://rss.cnn.com/rss/edition.rss" /> CNN Top Stories</label>
+ <!--<label><input type="radio" name="demo" value="feed:http://sophist4ever.pixnet.net/blog/feed/rss" /> 假圖天國 <a href="http://sophist4ever.pixnet.net/blog" target="_blank" class="link famfamfam_sprite application_double">link</a></label>
+ <label><input type="radio" name="demo" value="feed:http://richter.pixnet.net/blog/feed/rss" /> 地圖會說話 <a href="http://richter.pixnet.net/blog" target="_blank" class="link famfamfam_sprite application_double">link</a></label>
+ <label><input type="radio" name="demo" value="feed:http://playpcesor.blogspot.com/feeds/posts/default" /> 電腦玩物 <a href="http://playpcesor.blogspot.com/" target="_blank" class="link famfamfam_sprite application_double">link</a></label>
+ <label><input type="radio" name="demo" value="feed:http://www.president.gov.tw/RSS.aspx?tabid=131&amp;moduleid=514" /> 總統府新聞稿</label>-->
+ </p>
+ </div>
+ <div id="blog_entry" class="entry">
+ <p><label><span>ID/Username for <span><span class="feed_type_name">:</span><input type="text" size="14" id="username" /></label></p>
+ <p>Some website doesn't provide full text RSS.</p>
+ </div>
+ <div id="feed_entry" class="entry">
+ <p><label><span>RSS Feed Address:</span><input type="url" size="40" id="rss" /></label></p>
+ <p>Only feed that has ever been subscribed could be accessed.</p>
+ </div>
+ <div id="file_entry" class="entry">
+ <p><label><span>Choice file:</span><input type="file" id="file" multiple /></label></p>
+ <p><label><span>Encoding:</span><input type="text" size="10" id="encoding" value="UTF-8" /></label></p>
+ <p>File will be processed directly without transmitting over the wire.</p>
+ </div>
+ <div id="wiki_entry" class="entry">
+ <p><label><span>Entry:</span><input type="text" size="14" id="wikipedia_entry" /></label></p>
+ </div>
+ <div id="html_entry" class="entry">
+ <p><label><span>URL:</span><input type="url" size="40" id="html_url" /></label></p>
+ <p>Only public webpages that has been indexed by search engines can be accessed.</p>
+ </div>
+ <button type="submit" id="source_panel_finish">Start</button>
+ </form>
+</div>
+<div id="help_panel" class="panel">
+ <h2>About</h2>
+ <div class="entry">
+ <p>Author: <a href="http://timc.idv.tw/" target="_blank">timdream</a>. Please feel free to leave <a href="http://blog.timc.idv.tw/posts/wordcloud/" target="_blank">comments</a>.</p>
+ <p>Technologies:</p>
+ <ul>
+ <li>Chinese: Self-developed N-gram analyzer</li>
+ <li>English: <a href="http://tartarus.org/~martin/PorterStemmer/" target="_blank">Porter Stemming Algorithm</a></li>
+ <li>HTML5 canvas</li>
+ <li>HTML5 FileReader API</li>
+ <li>HTML5 Web Workers API</li>
+ <li>Javascript 1.6 <a href="https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array" target="_blank">new Array functions</a></li>
+ </ul>
+ <p>Data feeds:</p>
+ <ul>
+ <li><a href="https://code.google.com/apis/feed/" target="_blank">Google Feed API</a></li>
+ <!--<li><a href="http://developer.yahoo.com/yql/" target="_blank">YQL API</a></li>-->
+ </ul>
+ <button>Close</button>
+ </div>
+</div>
+<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.5/jquery.min.js"></script>
+<script type="text/javascript" src="../jquery.wordcloud.js"></script>
+<script type="text/javascript" src="../wordfreq.js"></script>
+<script type="text/javascript" src="../wordcloud.js"></script>
+<script type="text/javascript">
+var T = {
+ title: 'Word Clouds for $1',
+ downloading: 'Downloading ...',
+ reading: 'Reading ...',
+ processing: 'Processing ...',
+ analyzing: 'Analyzing ...',
+ errorReading: 'Reading error, please try again later.',
+ errorWordCount: 'Not enough word/phrases to show.',
+ startList_1: 'HTML5 Word Cloud',
+ startList_1C: 45,
+ startList_2: '文字雲',
+ startList_2C: 35,
+ startList_3: 'Text Analyzer',
+ startList_3C: 30,
+ startList_4: 'Click to start',
+ startList_4C: 26,
+ readyList_1: 'Analyzing complete',
+ readyList_1C: 45,
+ readyList_2: '$1 phrases in total',
+ readyList_2C: 26,
+ readyList_3: 'Maximum count $2 times',
+ readyList_3C: 20,
+ readyList_4: 'Click to start',
+ readyList_4C: 17
+};
+</script>
+</body>
+</html>
BIN  famfamfam_sprites.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 famfamfam_sprites.txt
@@ -0,0 +1,17 @@
+disk: data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAH+SURBVBgZBcE9i11VGAbQtc/sO0OCkqhghEREAwpWAWUg8aMVf4KFaJEqQtAipTZWViKiCGOh2Ap2gmJhlSIWFsFOxUK0EsUM3pl79n4f12qHb3z3Fh7D83gC95GOJsDe0ixLk5Qq/+xv/Lw9Xd+78/HLX3Y8fXTr2nWapy4eCFKxG7Fby97SnDlYtMbxthyfzHO//nl85fNvfvnk8MbX5xa8IHx1518Vkrj54Q+qQms2vVmWZjdiu5ZR2rT01166/NCZg/2PFjwSVMU6yjoC1oq+x6Y3VbHdlXWExPd379nf7Nmejv2Os6OC2O4KLK0RNn3RNCdr2Z5GJSpU4o+/TkhaJ30mEk5HwNuvX7Hpi76wzvjvtIwqVUSkyjqmpHS0mki8+9mPWmuWxqYvGkbFGCUAOH/+QevYI9GFSqmaHr5wkUYTAlGhqiRRiaqiNes6SOkwJwnQEqBRRRJEgkRLJGVdm6R0GLMQENE0EkmkSkQSVVMqopyuIaUTs0J455VLAAAAAODW0U/GiKT0pTWziEj44PZ1AAAAcPPqkTmH3QiJrlEVDXDt0qsAAAAAapa5BqUnyaw0Am7//gUAAAB49tEXzTmtM5KkV/y2G/X4M5fPao03n/sUAAAAwIX7y5yBv9vhjW/fT/IkuSp5gJKElKRISYoUiSRIyD1tufs/IXxui20QsKIAAAAASUVORK5CYII=
+award_star_bronze_1: data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAJvSURBVDjLhZNNSFRRFIC/N++9eWMzhkl/ZJqFMQMRFvTvImkXSdKiVRAURBRRW1eZA9EqaNOiFlZEtQxKyrJwUS0K+qEQzaTE/AtLHR3HmffuvafFNINDWGdz7z2c7+Nyzr2WiFAIffaMBDW1+B0diAgYgxiDiCDG4DU1QfcLos+fWAXGYUGIUsXiAliUFER+sBAhVCIIVB7QGtEat1oTbcwVz2LMfwR+gPg+oY0bEa3x6sHdUoVdniMUj0M2i/j+PwVJa2QUu7YWp34D7mqNWdNApD6Ks24dpvcL4gfJRQXevbutjI4lGRzCS9iYukPo5dvxVqWQvn6k/2uyoudd60LGEhG43VBGyI4j2ADZ7vDJ8DZ9Img4hw4cvO/3UZ1vH3p7lrWRLwGVneD4y6G84NaOYSoTVYIFIiAGvXI3OWctJv0TW03jZb5gZSfzl9YBpMcIzUwdzQsuVR9EyR3TeCqm6w5jZiZQMz8xsxOYzDTi50AMVngJNgrnUweRbwMPiLpHrOJDOl9Vh6HD7GyO52qa0VPj6MwUJpNC5mYQS/DUJLH3zzRp1cqN8YulTUyODBBzt4X6Ou870z2I8ZHsHJLLYNQ8jusQ6+2exJf9BfivKdAymKZiaVdodhBRAagAjIbgzxp20lwb6Vp0jADYkQO6IpHfuoqInSJUVoE2HrpyRQ1tic2LC9p3lSHWPh2rJfL1MeVP2weWvHp8s3ziNZ49i1q6HrR1YHGBNnt1dG2Z++gC4TdvrqNkK1eHj7ljQ/ujHx6NyPw8BFIiKPmNpKar7P7xb/zyT9P+o7OYvzzYSUt8U+TzxytodixEfgN3CFlQMNAcMgAAAABJRU5ErkJggg==
+feed: data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAJFSURBVBgZBcHda5V1AADg5/d733Oc7tjOaNs5GC6KdrEwmpPRxG7spoKghOim7oK8y0MIEQRL+geGEIQ3UXQvSJ8IafZxUbjQhRDZoU60iYsSc9t5v87b84TsVe3mrBWpHoCICIAIACixYTUfOJM2Z62YO97TOULSIKaEQAyESAzEgISAgLpi48de87MLUqmezhGyhO4SCW7f4O81YiSJiCQIkbqmNcXMIjMXeilIGsQxDp8AnKDY5teL3PyU6h4CdY3Av7cYu58R0QghZWeT9fP0v2V7i8Y4j77As2c5sAwIFAXDgjInJxURAzub/PwxMZBGphZYeIWJWZ44xdo5bl4kK8kzioohUUREd4kXP+Kpd3nkee72+epNBleAxdfoLJBlDEuKkpxoBAkBjXGm53n8ZZ45S/shrr7P75eBo6eo9zAsKCqGRBEB/1zj89e5eo7tLRr7ePJtWg9wZZV7t2i2OPQcw5JiRE4UESN1ZPc2g0tceos/LtPYx9HTaPDNe8Dhl9gtyStyUiMIJDXLp2m0GHzN2gdMzdPq0F3k+pcc/4+x/UwepKzIiSDWTB/iwBLT8xw8xt07rJ8HHj7GbkX/B+DBxyhrciIQ2N2i2AG2fiPL+OsXoNVlWPDnDaC5l6qiJJWjLlHxxRs0JhhcIyvp/8SHJylKdiu++4Tr31NW7B8nkrwzp627d9nkHM0Wsea+GSY6tDvESEyY6TIxyZ4GSUp/nTubqyF7WrvZtaKrZ4QSQ+TIMUSJHCVypGhaHW448z+h1tLAgvKk7gAAAABJRU5ErkJggg==
+page_world: data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAMZSURBVBgZBcFLaFxVHMDh3zn33Dt38poknTSJTVva1LaKxpQ07UJLKlQRTYVUcKNCwWUtCuJWXLkQxIVCl1kIIaCCG0GwXdgkamJS0hLHWs2znbym05m8JjP3nnv+fp8SEQBe+fT21XRT6h2t6ANCQAGgAFEgDuvcfLkot9R26ZOxG4MRgBIRAF7/fGLs2+t9z2itmgU8BAAARACEwm7MyHSZ9ZVaJTd3v3X8xmDNAABoT50KjNf81yaeVgoUiINEHNYK+3HCxacbOX/SMOkKdeJOlwY++KnFAAAotdQ0/PuEV4qeUE0snvg0+Yfp6XqD+rAdjQIcnU0Bg/2d/BKspxfW6oeViHDlm9euvvTsueGXT14Ev5WNSsjufo2NJzkWV6c4f+x9WjPddDc7GtMeKd9QqUa8+9WM9f5sGLsw0Nv33atnLnmSbqa8H7ARBcwXfKCF57sCbt0d5anMc1RshpVywmIx4njW5/vJtUh3tmc/7j/WG/yjEwqR5b8tw9/5mIe1efIHbpNvzHO64yCTuR9IBR5h4BEGPoIGpdGHs50XSiZiubKK5xqYXdwlCUvsHv2NOTPN1KMchw50UCwv4BtN4HmkjMYBImAC46fL1RLFxGeiuEdp2yMIY1pSLxBtHmX/8R/ICUecRPieAgFBkThIHJjt3Z3iKcKuOtvB0rrD+S0s5QP2ZqAuzNLeukZlfwctKZQojAYHhD4kVtC55fkfo60qtfI4qdQKKooIwibCjCXVPMXxTI2Zfx9wpK0XAZyAAL6nsZHFFFe3vvx58tc3L53tP1Jo81mq1YicQRpX6c4+pFaGO/kM2Z63mZuNcQDASIdPXHOY8S+mls5e7728+djMDvR56kRDiE0CGrOWuwtFVosHeevyZ6TSGURABO5tWsQJcdViAKa/nr137sPR6nbhQfrm8ijOWYyfhvoXOdTzHnPlOlTZ4gREK7RTGKOcTZw1AAAublv/aGgouxdLvYhoBBwAkEk7AEQg7SuUwvme2kmsyysRAaD/2s1rNpYhpdQZQeoAABAQQBAAEACqzrk7Gkb+B+5ReIstDYkxAAAAAElFTkSuQmCC
+drive: data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAADsSURBVCjPpZE9SgRBEIW/XnvWwB+ExUAXBDNvsTCTeAtP4AkEz+MNnGSHuYHBRgObCAaCmAiCU93VZdC9g5HJVlBJvfe+osoZ/9eMfQUeYFhrrUQCgYAgCCPS3TXgjGE178+RyZO3quh5be47D/HxjHcOAStD441Trhke6NxmNe8XfJXgiOE4oOKEI1q2jXtZX9SGYCXcpl7xyVPnhW8+GDESSsJIJBTDc4zgpQZB2eCYFa+RuEJZIrUfiUQUxZEKZpcRCPgRRUnckEjYH4yRsmCBTsHZvwNdEvE/7fOtMObbIUi5Z8Za6/b+5i8QHogENhlMkQAAAABJRU5ErkJggg==
+arrow_undo: data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAIJSURBVDjLpVM9aJNRFD35GsRSoUKKzQ/B0NJJF3EQlKrVgijSCBmC4NBFKihIcXBwEZdSHVoUwUInFUEkQ1DQ4CKiFsQsTrb5xNpgaZHw2Uog5t5zn0NJNFaw0guX97hwzuPcc17IOYfNlIdNVrhxufR6xJkZjAbSQGXjNAorqixSWFDV3KPhJ+UGLtSQMPryrDscPwLnAHOEOQc6gkbUpIagGmApWIb/pZRX4fjj889nWiSQtgYyBZ1BTUEj6AjPa0P71nb0Jfqwa+futIheHrzRn2yRQCUK/lOQhApBJVQJChHfnkCqOwWEQ+iORJHckUyX5ksvAEyGNuJC+s6xCRXNHNxzKMmQ4luwgjfvZp69uvr2+IZcyJ8rjIporrxURggetnV0QET3rrPxzMNM2+n7p678jUTrCiWhphAjVHR9DlR0WkSzf4IHxg5MSF0zXZEuVKWKSlCBCostS8zeG7oV64wPqxInbw86lbVXKEQ8mkAqmUJ4SxieeVhcnANFC02C7N2h69HO2IXeWC8MDj2JnqaFNAMd8f3HKjx6+LxQRmnOz1OZaxKIaF1VISYwB9ARZoQaYY6o1WpYCVYxt+zDn/XzVBv/MOWXW5J44ubRyVgkelFpmF/4BJVfOVDlVyqLVBZI5manPjajDOdcswfG9k/3X9v3/vfZv7rFBanriIo++J/f+BMT+YWS6hXl7QAAAABJRU5ErkJggg==
+arrow_refresh: data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAI/SURBVDjLjZPbS9NhHMYH+zNidtCSQrqwQtY5y2QtT2QGrTZf13TkoYFlzsWa/tzcoR3cSc2xYUlGJfzAaIRltY0N12H5I+jaOxG8De+evhtdOP1hu3hv3sPzPO/z4SsBIPnfuvG8cbBlWiEVO5OUItA0VS8oxi9EdhXo+6yV3V3UGHRvVXHNfNv6zRfNuBZVoiFcB/3LdnQ8U+Gk+bhPVKB3qUOuf6/muaQR/qwDkZ9BRFdCmMr5EPz6BN7lMYylLGgNNaKqt3K0SKDnQ7us690t3rNsxeyvaUz+8OJpzo/QNzd8WTtcaQ7WlBmPvxhx1V2Pg7oDziIBimwwf3qAGWESkVwQ7owNujk1ztvk+cg4NnAUTT4FrrjqUKHdF9jxBfXr1rgjaSk4OlMcLrnOrJ7latxbL1V2lgvlbG9MtMTrMw1r1PImtfyn1n5q47TlBLf90n5NmalMtUdKZoyQMkLKlIGLjMyYhFpmlz3nGEVmFJlRZNaf7pIaEndM24XIjCOzjX9mm2S2JsqdkMYIqbB1j5C6yWzVk7YRFTsGFu7l+4nveExIA9aMCcOJh6DIoMigyOh+o4UryRWQOtIjaJtoziM1FD0mpE4uZcTc72gBaUyYKEI6khgqINXO3saR7kM8IZUVCRDS0Ucf+xFbCReQhr97MZ51wpWxYnhpCD3zOrT4lTisr+AJqVx0Fiiyr4/vhP4VyyMFIUWNqRrV96vWKXKckBoIqWzXYcoPDrUslDJoopuEVEpIB0sR+AuErIiZ6OqMKAAAAABJRU5ErkJggg==
+application_double: data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAGnSURBVDjLnZOxilNBGIW/mXt3CZsYQQtjJYqPkE4L8Q20WARbmxWEFQvBXrByQdDKF3CL1QcQH8DOKmVIkWIFbdybTe7M/x+Lm+zeFELcAz/DwJnD4eOf8OD5p4d37w2f/qrUwR25k3PG5cgMl5AZ5k5/O81Ho+mHo7e7RyxVDu8M97c63TjosIk61cz2gfOAWVKc/T5hU50mxfa9lInXj29vHPDkzYT1ADkAi2x8/jq6fpy7N37+8eJfPHqX+zx7/1397VSNRtOXJRIAMcB4tnOr19thcHWjMt1qZu9KcwMghEBVi+o/eZSW81nARXiUOaXzgBYPuTCH7I65Y1nNyKlN3BxcwtwoLTUNItDmoRhQECWRECIhGKEQhUfK3Pg8G+V0PPm2d5Du5zpxZXDtrA0BCoEkCkEMBWUAC8Ji09TNG8NqXnz8IUnK7sruSmaqzTQ30yIlndZJszrpZJ4kSY9efVnfqjaP9hmBECNFEQkxEIuVP1O2A9Z4LB8Xy3OlrbbfbD1gOp4c7h2k3VwnzAx3Jy0WzY90Q6ZmK93xBsNh0JL8RfUXD1Ut4VHY1QEAAAAASUVORK5CYII=
+accept: data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAKfSURBVDjLpZPrS1NhHMf9O3bOdmwDCWREIYKEUHsVJBI7mg3FvCxL09290jZj2EyLMnJexkgpLbPUanNOberU5taUMnHZUULMvelCtWF0sW/n7MVMEiN64AsPD8/n83uucQDi/id/DBT4Dolypw/qsz0pTMbj/WHpiDgsdSUyUmeiPt2+V7SrIM+bSss8ySGdR4abQQv6lrui6VxsRonrGCS9VEjSQ9E7CtiqdOZ4UuTqnBHO1X7YXl6Daa4yGq7vWO1D40wVDtj4kWQbn94myPGkCDPdSesczE2sCZShwl8CzcwZ6NiUs6n2nYX99T1cnKqA2EKui6+TwphA5k4yqMayopU5mANV3lNQTBdCMVUA9VQh3GuDMHiVcLCS3J4jSLhCGmKCjBEx0xlshjXYhApfMZRP5CyYD+UkG08+xt+4wLVQZA1tzxthm2tEfD3JxARH7QkbD1ZuozaggdZbxK5kAIsf5qGaKMTY2lAU/rH5HW3PLsEwUYy+YCcERmIjJpDcpzb6l7th9KtQ69fi09ePUej9l7cx2DJbD7UrG3r3afQHOyCo+V3QQzE35pvQvnAZukk5zL5qRL59jsKbPzdheXoBZc4saFhBS6AO7V4zqCpiawuptwQG+UAa7Ct3UT0hh9p9EnXT5Vh6t4C22QaUDh6HwnECOmcO7K+6kW49DKqS2DrEZCtfuI+9GrNHg4fMHVSO5kE7nAPVkAxKBxcOzsajpS4Yh4ohUPPWKTUh3PaQEptIOr6BiJjcZXCwktaAGfrRIpwblqOV3YKdhfXOIvBLeREWpnd8ynsaSJoyESFphwTtfjN6X1jRO2+FxWtCWksqBApeiFIR9K6fiTpPiigDoadqCEag5YUFKl6Yrciw0VOlhOivv/Ff8wtn0KzlebrUYwAAAABJRU5ErkJggg==
+stop: data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAJOSURBVDjLpZI9T1RBFIaf3buAoBgJ8rl6QVBJVNDCShMLOhBj6T+wNUaDjY0WmpBIgYpAjL/AShJ+gVYYYRPIony5IETkQxZ2770zc2fGYpflQy2MJzk5J5M5z/vO5ESstfxPxA4erL4Zuh4pLnoaiUZdq7XAGKzRJVbIBZ3JPLJaD9c/eCj/CFgZfNl5qK5q8EhTXdxxLKgQjAFr0NK0ppOpt9n51D2gd2cmsvOElVcvOoprKvuPtriNzsY8rH+H0ECoQEg4WklY1czP8akZby51p6G3b6QAWBl43llSVTlUfuZE3NmYh9Vl0HkHSuVq4ENFNWFdC+uJ5JI/9/V2Y//rkShA1HF6yk/VxJ0f07CcgkCB7+fSC8Dzcy7mp4l9/khlUzwecaI9hT+wRrsOISylcsphCFLl1RXIvBMpYDZJrKYRjHELACNEgC/KCQQofWBQ5nuV64UAP8AEfrDrQEiLlJD18+p7BguwfAoBUmKEsLsAGZSiFWxtgWWP4gGAkuB5YDRWylKAKIDJZBa1H8Kx47C1Cdls7qLnQTZffQ+20lB7EiU1ent7sQBQ6+vdq2PJ5dC9ABW1sJnOQbL5Qc/HpNOYehf/4lW+jY4vh2tr3fsWafrWzRtlDW5f9aVzjUVj72FmCqzBypBQCKzbjLp8jZUPo7OZyYm7bYkvw/sAAFMd7V3lp5sGqs+fjRcZhVYKY0xupwysfpogk0jcb5ucffbbKu9Esv1Kl1N2+Ekk5rg2DIXRmog1Jdr3F/Tm5mO0edc6MSP/CvjX+AV0DoH1Z+D54gAAAABJRU5ErkJggg==
+cross: data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAIhSURBVDjLlZPrThNRFIWJicmJz6BWiYbIkYDEG0JbBiitDQgm0PuFXqSAtKXtpE2hNuoPTXwSnwtExd6w0pl2OtPlrphKLSXhx07OZM769qy19wwAGLhM1ddC184+d18QMzoq3lfsD3LZ7Y3XbE5DL6Atzuyilc5Ciyd7IHVfgNcDYTQ2tvDr5crn6uLSvX+Av2Lk36FFpSVENDe3OxDZu8apO5rROJDLo30+Nlvj5RnTlVNAKs1aCVFr7b4BPn6Cls21AWgEQlz2+Dl1h7IdA+i97A/geP65WhbmrnZZ0GIJpr6OqZqYAd5/gJpKox4Mg7pD2YoC2b0/54rJQuJZdm6Izcgma4TW1WZ0h+y8BfbyJMwBmSxkjw+VObNanp5h/adwGhaTXF4NWbLj9gEONyCmUZmd10pGgf1/vwcgOT3tUQE0DdicwIod2EmSbwsKE1P8QoDkcHPJ5YESjgBJkYQpIEZ2KEB51Y6y3ojvY+P8XEDN7uKS0w0ltA7QGCWHCxSWWpwyaCeLy0BkA7UXyyg8fIzDoWHeBaDN4tQdSvAVdU1Aok+nsNTipIEVnkywo/FHatVkBoIhnFisOBoZxcGtQd4B0GYJNZsDSiAEadUBCkstPtN3Avs2Msa+Dt9XfxoFSNYF/Bh9gP0bOqHLAm2WUF1YQskwrVFYPWkf3h1iXwbvqGfFPSGW9Eah8HSS9fuZDnS32f71m8KFY7xs/QZyu6TH2+2+FAAAAABJRU5ErkJggg==
+arrow_out: data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAHkSURBVDjL3ZNvT1JhGMafb3G+TQqKECNFRIEDcvgXmB5IPNJmTdbC1SQ0S1xzZKXyT41TdpCOMyYtiXS9aW2uD8EbPsHV87RRmyLrdc92vbt/1/U8930/ZLYxASbpSwgz9SCin2+CHtJJwYoLgbITvvcOeN7a4S6NgTB45+cmCucvu8JMFOZCZQHpr0tYO12Ga9cKwpJz5xvIfH+GR2dxRGp+uSOs8Jxv39GKV+/gYS2OlXoSfNECMnMSRKw+hdS3BLI/Mlho3MPUR88lE+++ozlfjWG1kYJUCcNRsMCWM4NM02vf/hTgwsf+1uLpfTw4mcOtQ0G9aCDINiWmRiAdiAz+HTC6Nfi3QKx6uckjT3Pi0K1c1QPnzojahtsi3Zr2L/rfDGin5fE3o+pVxeYXRmVw3dA0Pddzfwz8Co82LFVERMuTbEyXJjGUMaqBgoBQ0Qfjmq5lWO3n9E/76IK8s4PCYHCytoDZgwhsWXPzosGNdYPszY1jTonBnxVgSuuhe6KhyfRDJGsJ3P0gQSqLDG7RBeE6PeF6Wie7X/MI5N2YLonoX+oFce1ZsXicQOJoHs68FdbNznBbAytaREthSHIE2lQPCF8cgT0/jLHtIQbD8sqEbrBuWYM+mqx93ANN8hp+AQOPtI0tirA3AAAAAElFTkSuQmCC
+arrow_in: data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAHqSURBVDjL3ZHbThpRFIZ5i3kcLRYPqIgUGcDhNKBAqyKCobTR2NhiKmCstcWmBmtLPaCO4CQ6SBWVKInx0N70KbjhCf7O3ia0ZS686F0vVrL3Xvv7VvIvFQBVuOITQxfe6tj5IEPu9xW/ZxGcu2aJnAksxW9eYP42hmB5oBY48zAjJ240QoP7HH3j8xYhWgwiUgiAyxpFlTxZmL2ewvrPNBJX0wid+TF0zCsEHtEKGcbT4igWK0k8OwzBumGo0uZoeUCYuZzE0vUcVn6k8OSbUyFwyfDbSgKvShOIFsZgWTfU2K96pv5huOSm8KfvS/AXHAqBQ2CxcJFAsjwDe5YFgWkGdzCPoSMXHhed8BXs8B7YFALbVh/6Nx+RyWAzevR91qEu+Jf6XwRuecdkTSRp27YcVtaoCLE33Qn9sha6D+3oSrVB+07zO0RXzsx4chxmT18ifhqjSTcKej5qMbkfRVQM12EqILA8uRaRgnguhRE7mqJrahR0y5MjYgi+TTfsq1a0vVELVODYMVUJ/Lo0jZG8768d/1md71uhS2nBZxwYzwXRn2bxMNksqLgtoxgQ/RjOe2HK9FCrYaVLIehY1KB9oYVpnVfXnKscrMsmqBNNEm2a13ol05c7+L7SzD1gWpLNVXW8SST3X7gvtJUuvnAlAAAAAElFTkSuQmCC
+comment: data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAEvSURBVDjLY/j//z8DJZiBagZEtO8QAuKlQPwTiP/jwbuAWAWbARtXHrz1//efv//xgS0n74MMuQ3EbHADgBweIP7z99+//x++/fv/8tO//88+/vv/5P2//w/f/ft/782//7df/f1/5xXE8OoFx0GGmCEbIJcz9QBY8gVQ47MP//4/Bmp+8Pbf/7tQzddf/P1/9RnEgM5VZ0EGeGM14ClQ86N3UM2v//2/9RKi+QpQ88UnuA2AewHk/PtAW++8/vv/JlDzted//18Gar7wBGTAH7ABtYtOgAywxBqIIEOQAcg1Fx7/BRuMFoicuKLxDyzK5u64Cjfo/ecfYD5Q/DLWaMSGgQrvPH/3FabxOxDXEp0SgYp7Z267AtL4BYgLSUrKQA1KQHwPiFPolxcGzAAA94sPIr7iagsAAAAASUVORK5CYII=
+comments: data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAG/SURBVDjLjZK9T8JQFMVZTUyc3IyJg4mDi87+GyYu6qB/gcZdFxkkJM66qJMGSNRBxDzigJMRQ1jQ4EcQ+SgVKB+FtuL13EdJxNDq8Ev7Xu85797T51nwhqeAH5w6cAxWwDgReX7jwYfdaCIraroptB7NLlVQrOoiGEsL1G06GZyxuILicsMUH3VTlOqGKNUMUdTacj+j1Nng0NGAT2WxYosK1bbIVVoiW27J9V8G57WWKVSczMV5iK+Tudv1vVh5yXdlLQN+os4AFZss2Ob82CCgQmhYHSnmkzf2b6rIhTAaaT2aXZALIRdCLgRtkA1WfYG4iKcVYX52JIs7EYvFmJ8wGiEXQi6EXAhdyn2MxQaPcg68zIETTvzyLsPzWnwqixVbhFwI3RFykes+A9vkIBKX4jCoIxdCLrI4/0OcUXXK4/1dbbDBS088xGGCCzAJCsiF2lanT8xdKNhHXvRarLFBqmcwCrbAhL32+kP3lHguETKRsNlbqUFPeY2OoikW62DNM+jf2ibzQNN0g5ALC75AGiT59oIReQ+cDGyTB+TC4jaYGXiRXMTD3AFogVmnOjeDMRAC025duo7wH74BwZ8JlHrTPLcAAAAASUVORK5CYII=
+help: data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAKkSURBVDjLpZPdT5JhGMb9W+BPaK3matVqndXWOOigA6fmJ9DUcrUMlrN0mNMsKTUznQpq6pyKAm8CIogmypcg8GIiX8rHRHjhVbPt6o01nMvZWge/k3vP9duuZ/edAyDnf/hjoCMP2Vr3gUDj3CdV6zT1xZ6iFDaKnLEkBFOmPfaZArWT5sw60iFP+BAbOzTcQSqDZzsNRyCNkcVoaGghzDlVQKylOHJrMrUZ2Yf52y6kc36IxpyoH1lHF7EBgyMKV4jCJ5U/1UVscU4IZOYEa3I1HtwI01hwxlDLhDoJD/wxGr5YGmOLAdRIrVCuhmD3JdA6SQabx12srGB0KSpc86ew4olDOGjH4x4z0gdHDD9+c4TaQQtq+k2Yt0egXYugTmoVZgV9cyHSxXTtJjZR3WNCVfcK/NE0ppYDUNu2QTMCtS0IbrsOrVMOWL27eNJtJLOCDoWXdgeTEEosqPxoBK/TwDzWY9rowy51gJ1dGr2zLpS2aVH5QQ+Hbw88sZ7OClrGXbQrkMTTAQu4HXqUv9eh7J0OSfo7tiIU+GItilpUuM/AF2tg98eR36Q+FryQ2kjbVhximQu8dgPKxPMoeTuH4tfqDIWvCBQ2KlDQKEe9dBlGTwR36+THFZg+QoUxAL0jgsoOQzYYS+wjskcjTzSToVAkA7Hqg4Spc6tm4vgT+eIFVvmb+eCSMwLlih/cNg0KmpRoGzdl+BXOb5jAsMYNjSWAm9VjwesPR1knFilPNMu510CkdPZtqK1BvJQsoaRZjqLGaTzv1UNp9EJl9uNqxefU5QdDnFNX+Y5Qxrn9bDLUR6zjqzsMizeWYdG5gy6ZDbk8aehiuYRz5jHdeDTKvlY1IrhSMUxe4g9SuVwpdaFsgDxf2i84V9zH/us1/is/AdevBaK9Tb3EAAAAAElFTkSuQmCC
+color_wheel: data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAMOSURBVDjLVZNNaBxlAIafb+ab2Z3N7Oxv/nYTEyv2LzQJpKBgrQqNUKmY4kUIXqUHT70p9iB48CKIiN5E0It6KFiwiv9FpAVpKUggNc3mZ7vpJpv9n93ZnZ35PNRI+8B7e9/n9gqlFAeIVUfPeN3zh0R0eVpYM1OanhvTCEY0f3tU79+ctnpfHM73fuQhxIHAWHnmkOGXPjgZyS09l5hnNv4YOdMhoQmigzqGt4nhfeub1fpnVsl/e+hMv/q/QKy+Me0EO5dfso/OvzB8grgV4HGXJC7jwAQ2oxxDuC36xZ+Rhe+v6iutZf2iqklReNe0tPSHZ2Nz84ujR7ht3iJKjcexiOIQI8SiixxcR7QtRORFlK7O9t0rlyy4KBEj5+YisVeez85wy9zGIUeGDDYhDhYOITYuoh2BvTJ68y7B0GnCym8XGq+KL2U0MrE8Z2SRVhqdPmlCsvgk8RlCkgAivRbUNKj1YPMeeu4wcnjRql7/+jVpyvxsPjbK3whi5LEAB0WWgBRgqwAaFah04X4V7puwdwddz+FXjJMSbXI8aSTYCgU2oKMwEdgCEoDhug/G5SjsmFDUoV+DXJ7BnpiUVCNBaJqEXfDVfwG6CjoKnF4crZGCVvNBug0IPXzPZOCnAunfk8W6ro7H2gK3A02gGoDeA1MDGx2nkYG6C24bvDaMSzq7ZfxBsiC7O+aNDaWOn0oLfl0HMwDlQRCAHYUkEGvFkLsp2G9Bo0n41AiNG6sMBvY1yZr6/JsV//XZZ3WZaEp2t6DvgWFA1QRHQbwjSDeTUGvCiSPU1ovU/typQPIrTV0yrrl3vE+/+8XlaCIgq8H+BtSLUN2C2ibsl8ArR+HYGE0rwvbvRTr96HsL6od1CUDDf+enK92JwT+982cWEswvRmiug6qAr0E4AV4uoFXosnV1g8bN5kcp7E8eOZOYKtmUqm/ZiDdfPhV3Zp6IM5k0SIUBstwmXKvCX5UdM6y9n2b34wV1IXxEcEBU3J4dprU0zODpjFBTIyoIxgjXxlB/PIl1eUmdLjzc/xceOVXddrB6BQAAAABJRU5ErkJggg==
239 jquery.wordcloud.js
@@ -0,0 +1,239 @@
+/*!
+
+ Simple <canvas> Word Cloud
+ by timdream
+
+ usage:
+ $('#canvas').wordCloud(settings); // draw word cloud on #canvas.
+ $.wordCloudSupported // return true if the browser checks out
+
+ available settings
+ fontFamily: font list for text.
+ gridSize: 8,
+ ellipticity: ellipticity of the circle formed by word.
+ drawMask: true to debug mask to show area covered by word.
+ maskColor: color of the debug mask.
+ maskGridWidth: width of the mask grid border.
+ wordColor: color for word.
+ backgroundColor: background to cover entire canvas or the detect against.
+ wait: wait N ms before drawing next word.
+ abortThreshold: abort and execute about() when the browser took more than N ms to draw a word. 0 to disable.
+ abort: abort handler.
+ weightFactor:
+ wordList: 2d array in for word list like [['w1', 12], ['w2', 6]]
+ clearCanvas: clear canvas before drawing. Faster than running detection on what's already on it.
+
+*/
+
+"use strict";
+
+(function ($) {
+
+ // http://jsfromhell.com/array/shuffle
+ Array.prototype.shuffle = function () { //v1.0
+ for(var j, x, i = this.length; i; j = parseInt(Math.random() * i), x = this[--i], this[i] = this[j], this[j] = x);
+ return this;
+ };
+
+ $.wordCloudSupported = (function () {
+ var $c = $('<canvas />'), ctx;
+ if (!$c[0] || !$c[0].getContext) return false;
+ ctx = $c[0].getContext('2d');
+ if (!ctx.getImageData) return false;
+ if (!ctx.fillText) return false;
+ if (!Array.prototype.some) return false;
+ if (!Array.prototype.push) return false;
+ return true;
+ }());
+
+ $.fn.wordCloud = function (options) {
+ if (!$.wordCloudSupported) return this;
+
+ var settings = {
+ fontFamily: '"Trebuchet MS", "Heiti TC", "微軟正黑體", "Arial Unicode MS", "Droid Fallback Sans", sans-serif',
+ gridSize: 8,
+ ellipticity: 0.65,
+ drawMask: false,
+ maskColor: 'rgba(255,0,0,0.3)',
+ maskGridWidth: 0.3,
+ wordColor: 'rgba(0,0,0,0.7)',
+ backgroundColor: '#fff', //opaque white = rgba(255, 255, 255, 1)
+ wait: 0,
+ abortThreshold: 0, // disabled
+ abort: $.noop,
+ weightFactor: 1,
+ wordList: [],
+ clearCanvas: true
+ };
+
+ if (options) {
+ $.extend(settings, options);
+ }
+
+ if (typeof settings.weightFactor !== 'function') {
+ var factor = settings.weightFactor;
+ settings.weightFactor = function (pt) {
+ return pt*factor; //in px
+ };
+ }
+
+ settings.gridSize = Math.max(settings.gridSize, 4);
+
+ var g = settings.gridSize,
+ ctx, grid, ngx, ngy, diffChannel, bgChannelVal,
+ escapeTime, timer,
+ exceedTime = function () {
+ return (
+ settings.abortThreshold > 0
+ && (new Date()).getTime() - escapeTime > settings.abortThreshold
+ );
+ },
+ isGridEmpty = function (x, y) {
+ var i = g*g*4,
+ imgData = ctx.getImageData(x*g, y*g, g, g);
+ while (i -= 4) {
+ if (imgData.data[i+diffChannel] !== bgChannelVal) return false;
+ }
+ return true;
+ },
+ updateGrid = function (gx, gy, gw, gh) {
+ var x = gw, y;
+ if (settings.drawMask) ctx.fillStyle = settings.maskColor;
+ out: while (x--) {
+ y = gh;
+ while (y--) {
+ if (!isGridEmpty(gx + x, gy + y)) {
+ grid[gx + x][gy + y] = false;
+ if (settings.drawMask) {
+ ctx.fillRect((gx + x)*g, (gy + y)*g, g-settings.maskGridWidth, g-settings.maskGridWidth);
+ }
+ }
+ if (exceedTime()) break out;
+ }
+ }
+ },
+ putWord = function (word, weight) {
+ var fontSize = settings.weightFactor(weight);
+ ctx.font = fontSize.toString(10) + 'px ' + settings.fontFamily;
+ var w = ctx.measureText(word).width,
+ h = Math.max(fontSize, ctx.measureText('m').width, ctx.measureText('\uFF37').width),
+ gw, gh;
+ if (fontSize < 4.5) return false; // Try not to fill the canvas with pixalized small text. Also fontSize === 0 means weightFactor wants the text skipped.
+ if (/[gpqy]/.test(word)) h *= 3/2;
+ gw = Math.ceil(w/g),
+ gh = Math.ceil(h/g);
+ var R = Math.floor(Math.sqrt(ngx*ngx+ngy*ngy)), T = ngx+ngy, r, t, points, x, y;
+ r = R;
+ while (r--) {
+ t = T;
+ points = [];
+ while (t--) {
+ points.push(
+ [
+ Math.floor(ngx/2+(R-r)*Math.cos(t/T*2*Math.PI) - gw/2),
+ Math.floor(ngy/2+(R-r)*settings.ellipticity*Math.sin(t/T*2*Math.PI) - gh/2)
+ ]
+ );
+ }
+ if (points.shuffle().some(
+ function (gxy) {
+ if (canFitText(gxy[0], gxy[1], gw, gh)) {
+ ctx.fillStyle = settings.wordColor;
+ ctx.fillText(word, gxy[0]*g + (gw*g - w)/2, gxy[1]*g + (gh*g - h)/2);
+ updateGrid(gxy[0], gxy[1], gw, gh);
+ return true;
+ }
+ return false;
+ }
+ )) return true;
+ }
+ return false;
+ },
+ canFitText = function (gx, gy, gw, gh) {
+ if (gx < 0 || gy < 0 || gx + gw > ngx || gy + gh > ngy) return false;
+ var x = gw, y;
+ while (x--) {
+ y = gh;
+ while (y--) {
+ if (!grid[gx + x][gy + y]) return false;
+ }
+ }
+ return true;
+ };
+
+
+ return this.each(function() {
+ if (this.nodeName.toLowerCase() !== 'canvas') return;
+ ngx = Math.floor($(this).attr('width')/g);
+ ngy = Math.floor($(this).attr('height')/g);
+ ctx = this.getContext('2d'),
+ grid = [];
+
+ /* in order to get more a correct reading on difference,
+ do clearRect */
+
+ var bctx = document.createElement('canvas').getContext('2d');
+
+ bctx.fillStyle = settings.backgroundColor;
+ bctx.clearRect(0, 0, 1, 1);
+ bctx.fillStyle = settings.backgroundColor;
+ bctx.fillRect(0, 0, 1, 1);
+ var bgPixel = bctx.getImageData(0, 0, 1, 1).data;
+ bctx.fillStyle = settings.wordColor;
+ bctx.fillRect(0, 0, 1, 1);
+ var wdPixel = bctx.getImageData(0, 0, 1, 1).data;
+
+ var i = 4;
+ while (i--) {
+ if (Math.abs(wdPixel[i] - bgPixel[i]) > 10) {
+ diffChannel = i;
+ bgChannelVal = bgPixel[i];
+ break;
+ }
+ }
+
+ //delete bctx; // break in strict mode
+
+ var x = ngx, y;
+ while (x--) {
+ grid[x] = [];
+ y = ngy;
+ while (y--) {
+ grid[x][y] = true;
+ }
+ }
+
+ if (settings.clearCanvas) {
+ ctx.fillStyle = settings.backgroundColor;
+ ctx.clearRect(0, 0, ngx*(g+1), ngy*(g+1));
+ ctx.fillRect(0, 0, ngx*(g+1), ngy*(g+1));
+ } else {
+ updateGrid(0, 0, ngx, ngy);
+ }
+
+
+ ctx.textBaseline = 'top';
+
+ clearTimeout($(this).data('wordCloud-timer'));
+
+ var i = 0;
+ timer = setInterval(
+ function () {
+ if (i >= settings.wordList.length) {
+ clearTimeout(timer);
+ return;
+ }
+ escapeTime = (new Date()).getTime();
+ putWord(settings.wordList[i][0], settings.wordList[i][1]);
+ if (exceedTime()) {
+ clearTimeout(timer);
+ settings.abort();
+ }
+ i++;
+ },
+ settings.wait
+ );
+ $(this).data('wordCloud-timer', timer);
+ });
+ }
+})(jQuery);
289 wordcloud.css
@@ -0,0 +1,289 @@
+html, body {
+ border: none;
+ margin: none;
+ padding: none;
+ overflow: hidden;
+ width: 100%;
+ height: 100%;
+ background-color: #353130;
+}
+
+body, input, select, button {
+ font: 1em sans-serif;
+ color: #000;
+}
+
+a {
+ color: #333;
+}
+
+.center_msg {
+ position: absolute;
+ top: 50%; left: 50%;
+ width: 200px; height: 100px;
+ margin-left: -100px; margin-top: -50px;
+ text-align: center;
+ border: 1px solid #ccc;
+ -webkit-border-radius: 10px;
+ -moz-border-radius: 10px;
+ border-radius: 10px;
+ background-color: #fff;
+ -webkit-box-shadow: 0 0 20px #ccc;
+ -moz-box-shadow: 0 0 20px #ccc;
+ box-shadow: 0 0 20px #ccc;
+ opacity: 0.9;
+}
+
+#loading {
+ background: #fff url('./beachball.gif') center center no-repeat;
+}
+
+#not_support {
+ width: 240px; height: 200px;
+ margin-left: -125px; margin-top: -110px;
+ padding: 10px;
+ text-align: left;
+}
+
+.center_btn {
+ position: absolute;
+ display: none;
+ top: 50%; left: 50%;
+ width: 450px; height: 250px;
+ margin-left: -225px; margin-top: -125px;
+ text-align: center;
+ border: 1px solid #ccc;
+ -webkit-border-radius: 10px;
+ -moz-border-radius: 10px;
+ border-radius: 10px;
+ text-indent: -10000px;
+}
+
+.center_btn:hover {
+ -webkit-box-shadow: 0 0 10px #000;
+ -moz-box-shadow: 0 0 10px #000;
+ box-shadow: 0 0 10px #000;
+}
+
+.center_btn:active {
+ -webkit-box-shadow: 0 0 10px #000 inset;
+ -moz-box-shadow: 0 0 10px #000 inset;
+ box-shadow: 0 0 10px #000 inset;
+}
+
+.error {
+ display: none;
+ border: 1px solid #c00;
+}
+
+#canvas {
+ position: absolute;
+ top: 0; left: 0;
+ width: 100%; height: 100%;
+}
+
+#controls {
+ display: none;
+ top: 80px;
+}
+
+#help {
+ top: 33px;
+}
+
+#language {
+ bottom: 10px;
+}
+
+#language li {
+ padding-left: 18px
+}
+
+.left_tool {
+ position: absolute;
+ left: 0;
+ border: 1px solid #ccc;
+ border-top-right-radius: 10px;
+ border-bottom-right-radius: 10px;
+ opacity: 0.8;
+ background-color: #fff;
+ white-space: nowrap;
+ overflow: hidden;
+ width: 100px;
+}
+
+.right_tool {
+ position: absolute;
+ right: 0;
+ border: 1px solid #ccc;
+ border-top-left-radius: 10px;
+ border-bottom-left-radius: 10px;
+ opacity: 0.8;
+ background-color: #fff;
+ white-space: nowrap;
+ overflow: hidden;
+ width: 100px;
+}
+
+.left_tool:hover, .right_tool:hover {
+ opacity: 1.0;
+}
+
+.left_tool > ul {
+ list-style: none;
+ margin: 0; padding: 0;
+}
+
+.left_tool > ul > li > a {
+ text-decoration: none;
+ color: #333;
+ font-size: 0.9em;
+}
+
+.left_tool > ul > li > a > .famfamfam_sprite {
+ float: left;
+ margin: 0 4px;
+}
+
+#social {
+ width: 90px;
+ height: 90px;
+ bottom: 10px;
+}
+
+#title {
+ position: absolute;
+ top: 0; left: 10%; width: 80%; height: 20px;
+ margin: 0; padding: 5px 10px;
+ border: 1px solid #ccc;
+ border-bottom-left-radius: 10px;
+ border-bottom-right-radius: 10px;
+ opacity: 0.8;
+ background-color: #fff;
+ overflow: hidden;
+ display: none;
+}
+
+#title > .famfamfam_sprite {
+ float: left;
+ margin-right: 4px;
+}
+
+#title:hover {
+ opacity: 1;
+}
+
+.panel {
+ position: absolute;
+ top: 50%; left: 50%;
+ width: 540px; height: 400px;
+ margin-left: -270px; margin-top: -200px;
+ padding: 0;
+ border: 1px solid #ccc;
+ -webkit-border-radius: 10px;
+ -moz-border-radius: 10px;
+ border-radius: 10px;
+ background-color: #fff;
+ display: none;
+ -webkit-box-shadow: 0 0 10px #000;
+ -moz-box-shadow: 0 0 10px #000;
+ box-shadow: 0 0 10px #000;
+}
+
+.panel h2 {
+ background-color: #e0e0e0;
+ margin: 0;
+ padding: 10px;
+ position: absolute;
+ top: 0; left: 0; right: 0;
+ font-size: 1.5em; height: 28px;
+ -webkit-box-shadow: 0 0 20px #ccc inset;
+ -moz-box-shadow: 0 0 20px #ccc inset;
+ box-shadow: 0 0 20px #ccc inset;
+ -moz-border-radius-topleft: 10px;
+ -moz-border-radius-topright: 10px;
+ -webkit-border-top-left-radius: 10px;
+ -webkit-border-top-right-radius: 10px;
+ border-top-left-radius: 10px;
+ border-top-right-radius: 10px;
+}
+
+.panel_left {
+ margin: 0;
+ position: absolute;
+ top: 48px; bottom: 0;
+ left: 0; width: 150px;
+ background-color: #e8e8e8;
+}
+
+.menu label {
+ display: block;
+}
+
+.panel_left label {
+ padding: 5px;
+ border-bottom: 1px solid #ccc;
+}
+
+.panel_left label.checked {
+ -webkit-box-shadow: 0 0 10px #ccc inset;
+ -moz-box-shadow: 0 0 10px #ccc inset;
+ box-shadow: 0 0 10px #ccc inset;
+ background-color: #fff;
+}
+
+/*.panel_left label:first-child {
+ border-top: 1px solid #ccc;
+}*/
+
+.panel_left label > input {
+ display: none;
+}
+
+.panel button {
+ font-size: 2em;
+ font-weight: bold;
+ position: absolute;
+ bottom: 10px; right: 10px;
+}
+
+.entry {
+ display: none;
+ position: absolute;
+ top: 48px; bottom: 0;
+ left: 150px; right: 0;
+ padding: 10px;
+}
+
+.entry label > span {
+ display: block;
+}
+
+.entry input {
+ max-width: 100%;
+}
+
+#facebook_like {
+ position: absolute;
+ bottom: 10px; right: 20px;
+}
+
+
+.famfamfam_sprite {display: block; background: transparent url('famfamfam_sprites.png') no-repeat; text-indent: -10000px; float: right; }
+.disk { background-position: 0 0; width: 16px; height: 16px}
+.award_star_bronze_1 { background-position: -18px 0; width: 16px; height: 16px}
+.feed { background-position: -36px 0; width: 16px; height: 16px}
+.page_world { background-position: -54px 0; width: 16px; height: 16px}
+.drive { background-position: -72px 0; width: 16px; height: 16px}
+.arrow_undo { background-position: 0 -18px; width: 16px; height: 16px}
+.arrow_refresh { background-position: -18px -18px; width: 16px; height: 16px}
+.application_double { background-position: -36px -18px; width: 16px; height: 16px}
+.accept { background-position: -54px -18px; width: 16px; height: 16px}
+.stop { background-position: -72px -18px; width: 16px; height: 16px}
+.cross { background-position: 0 -36px; width: 16px; height: 16px}
+.arrow_out { background-position: -18px -36px; width: 16px; height: 16px}
+.arrow_in { background-position: -36px -36px; width: 16px; height: 16px}
+.comment { background-position: -54px -36px; width: 16px; height: 16px}
+.comments { background-position: -72px -36px; width: 16px; height: 16px}
+.help { background-position: 0 -54px; width: 16px; height: 16px}
+.color_wheel { background-position: -18px -54px; width: 16px; height: 16px}
564 wordcloud.js
@@ -0,0 +1,564 @@
+
+"use strict";
+
+function t(id) {
+ var s = T[id];
+ if (!s) return id;
+ if (!s.replace) return s;
+ for (var i = 1; i < arguments.length; i++) {
+ s = s.replace(new RegExp('\\\$' + i.toString(10), 'g'), arguments[i]);
+ }
+ return s;
+}
+
+jQuery(function ($) {
+ var $c = $('#canvas'),
+ $toggleUI = $('.toggleUI'),
+ $loading = $('#loading'),
+ $error = $('#error'),
+ $loadingText = $('#loading > p'),
+ $errorText = $('#error > p'),
+ wordfreq = WordFreq({root: '../'}),
+ theme = [
+ {
+ fontFamily: '"Myriad Pro", "Lucida Grande", Helvetica, "Heiti TC", "微軟正黑體", "Arial Unicode MS", "Droid Fallback Sans", sans-serif',
+ wordColor: 'rgba(255,255,255,0.8)',
+ backgroundColor: '#353130'
+ },
+ {
+ fontFamily: '"Trebuchet MS", "Heiti TC", "微軟正黑體", "Arial Unicode MS", "Droid Fallback Sans", sans-serif',
+ wordColor: 'rgba(0,0,0,0.7)',
+ backgroundColor: 'rgba(255, 255, 255, 1)' //opaque white
+ },
+ {
+ // http://ethantw.net/projects/lab/css-reset/
+ fontFamily: 'Baskerville, "Times New Roman", "華康儷金黑 Std", "華康儷宋 Std", DFLiKingHeiStd-W8, DFLiSongStd-W5, "Hiragino Mincho Pro", "LiSong Pro Light", "標楷體", serif',
+ wordColor: '#fff',
+ backgroundColor: '#000'
+ }
+ ],
+ list, weightFactor, gridSize, themeid = 0;
+
+ function resetCanvasSize() {
+ var width = document.body.offsetWidth,
+ height = document.body.offsetHeight;
+
+ $c.attr(
+ {
+ height: height,
+ width: width
+ }
+ ).css({
+ width: width.toString(10) + 'px',
+ height: height.toString(10) + 'px',
+ top: '50%',
+ left: '50%',
+ marginLeft: '-' + (width/2).toString(10) + 'px',
+ marginTop: '-' + (height/2).toString(10) + 'px'
+ });
+ }
+
+ if (
+ !$.wordCloudSupported
+ || !WordFreq.supported
+ || !Array.prototype.forEach
+ || !Array.prototype.pop
+ || !Array.prototype.push
+ || !('onhashchange' in window)
+ ) {
+ $('#not_support').show();
+ return;
+ }
+
+ var changeUIState = {
+ start: function () {
+ $toggleUI.hide();
+ $loading.fadeOut(100);
+ $('#start').show();
+ resetCanvasSize();
+ $c.show().wordCloud({
+ wordColor: theme[themeid].wordColor,
+ backgroundColor: theme[themeid].backgroundColor,
+ fontFamily: theme[themeid].fontFamily,
+ wait: 50,
+ wordList: [
+ [t('startList_1'), t('startList_1C')],
+ [t('startList_2'), t('startList_2C')],
+ [t('startList_3'), t('startList_3C')],
+ [t('startList_4'), t('startList_4C')]
+ ],
+ abortThreshold: 200,
+ abort: changeUIState.too_slow
+ });
+ return false;
+ },
+ source: function () {
+ $toggleUI.hide();
+ $loading.fadeOut(100);
+ resetCanvasSize();
+ changeSource.apply($('input[name=source]:checked')[0]);
+ $('#source_panel').show();
+ return false;
+ },
+ ready: function () {
+ $toggleUI.hide();
+ $loading.fadeOut(100);
+ resetCanvasSize();
+ $('#title').show();
+ $c.show();
+ $('#ready').show();
+ return false;
+ },
+ draw: function () {
+ $toggleUI.hide();
+ $loading.fadeOut(100);
+ resetCanvasSize();
+ $('#title').show();
+ $('#controls').show();
+ $c.show();
+ setTimeout(
+ function () {
+ $c.wordCloud({
+ wordColor: theme[themeid].wordColor,
+ backgroundColor: theme[themeid].backgroundColor,
+ fontFamily: theme[themeid].fontFamily,
+ gridSize: gridSize,
+ weightFactor: weightFactor, //$c[0].offsetHeight*$c[0].offsetWidth/vol*0.5,
+ wordList: list,
+ abortThreshold: 500,
+ abort: changeUIState.too_slow
+ });
+ },
+ 0
+ );
+ return false;
+ },
+ loading: function (text) {
+ $toggleUI.hide();
+ $loadingText.text(text);
+ $loading.fadeIn(100);
+ $('#title').show();
+ return false;
+ },
+ error: function (text) {
+ $toggleUI.hide();
+ $loading.fadeOut(100);
+ $errorText.text(text);
+ $error.fadeIn(100);
+ return false;
+ },
+ too_slow: function () {
+ $toggleUI.hide();
+ $loading.fadeOut(100);
+ $('too_slow').show();
+ return false;
+ }
+ };
+
+ // post text processing functions
+
+ var postProcessFeedByDomain = {
+ 'pixnet.net': function (str) {
+ return str.replace(/\(.+?\.\.\.\)/g, '');
+ },
+ 'wretch.cc': function (str) {
+ return str.replace(/本篇文章引用自此/g, '');
+ }
+ };
+
+ function pass (str) {
+ return str;
+ }
+
+ // handleHash
+
+ function handleHash() {
+ if (window.location.hash) {
+ $c.wordCloud(); // stop current wordCloud;
+ switch (window.location.hash.substr(1, 4)) {
+ case 'feed':
+ updateTitle('feed', window.location.hash.substr(6));
+ changeUIState.loading(t('downloading'));
+ getFeedText(
+ window.location.hash.substr(6),
+ postProcessFeedByDomain[
+ window.location.hash.substr(6).match(/(\w+.\w+)\//)[1]
+ ] || pass,
+ processingFeed,
+ handleText
+ );
+ return;
+ break;
+ case 'html':
+ updateTitle('html', window.location.hash.substr(6));
+ changeUIState.loading(t('downloading'));
+ getHTMLText(
+ window.location.hash.substr(6),
+ pass,
+ processingHTML,
+ handleText
+ );
+ return;
+ break;
+ case 'file':
+ var f = $('#file')[0];
+ if (!f.files || !f.files.length) {
+ // not really getting files, show panel
+ $('input[value=file]').attr('checked', true);
+ window.location.hash = '#';
+ //changeUIState.source();
+ } else {
+ updateTitle('file', f.files[0].name);
+ changeUIState.loading(t('reading'));
+ getFileContent(
+ f.files,
+ pass,
+ readingFile,
+ handleText
+ );
+ }
+ break;
+ //default:
+ //do nothing
+ //break;
+ }
+ } else {
+ changeUIState.source();
+ }
+ }
+
+ window.onhashchange = handleHash;
+ if (window.location.hash) handleHash(); // only load when hash exists
+ else changeUIState.start(); // show start otherwise
+
+ // UI flow buttons
+
+ $('.start').bind(
+ 'click',
+ function () {
+ window.location.hash = '#';
+ changeUIState.source();
+ }
+ );
+
+ $('.ready').bind(
+ 'click',
+ changeUIState.draw
+ );
+
+ // Help/about panel
+
+ $('.help').bind(
+ 'click',
+ function () {
+ $('#help_panel, #help_panel .entry').show();
+ return false;
+ }
+ );
+
+ $('#help_panel button').bind(
+ 'click',
+ function () {
+ $('#help_panel').hide();
+ }
+ );
+
+ // interaction within source panel
+
+ var $s = $('input[name=source]');
+
+ function changeSource() {
+ var type = this.value.substr(0,4);
+ $('.entry').hide();
+ $(this).parent().addClass('checked').siblings().removeClass('checked');
+ $('#' + type + '_entry').show();
+ $('.feed_type_name').text($(this).parent('label').text());
+ };
+
+ $s.bind(
+ 'click',
+ changeSource
+ );
+
+ $('#source_panel_form').bind(
+ 'submit',
+ function () {
+ switch ($('input[name=source]:checked').val()) {
+ case 'demo':
+ window.location.hash = '#' + $('input[name=demo]:checked').val();
+ break;
+ case 'blog:blogger':
+ if (!$('#username').val()) return false;
+ window.location.hash = '#feed:' + 'http://' + $('#username').val() + '.blogspot.com/feeds/posts/default';
+ break;
+ case 'blog:pixnet':
+ if (!$('#username').val()) return false;
+ window.location.hash = '#feed:' + 'http://' + $('#username').val() + '.pixnet.net/blog/feed/rss';
+// function (str) {
+ // return str.replace(/\(.+?\.\.\.\)/g, '');
+ // },
+ break;
+ case 'blog:wretch':
+ if (!$('#username').val()) return false;
+ window.location.hash = '#feed:' + 'http://www.wretch.cc/blog/' + $('#username').val() + '&rss20=1';
+ break;
+ case 'blog:plurk':
+ if (!$('#username').val()) return false;
+ window.location.hash = '#feed:' + 'http://www.plurk.com/' + $('#username').val() + '.xml';
+ break;
+ case 'blog:twitter':
+ if (!$('#username').val()) return false;
+ window.location.hash = '#feed:' + 'http://twitter.com/statuses/user_timeline/' + $('#username').val() + '.rss';
+ break;
+ case 'feed':
+ if (!$('#rss').val()) return false;
+ window.location.hash = '#feed:' + $('#rss').val();
+ break;
+ case 'file':
+ if (!$('#file')[0].files.length) return false;
+ window.location.hash = '#file';
+ break;
+ case 'wiki':
+ if (!$('#wikipedia_entry').val()) return false;
+ window.location.hash = '#html:' + 'http://zh.wikipedia.org/zh-tw/' + encodeURIComponent($('#wikipedia_entry').val());
+ break;
+ case 'html':
+ if (!$('#html_url').val()) return false;
+ window.location.hash = '#html:' + $('#html_url').val();
+ break;
+ }
+ return false;
+ }
+ );
+
+ // get remote resource functions
+
+ function getFeedText(url, processText, beforeComplete, complete) {
+ $.getJSON(
+ 'https://ajax.googleapis.com/ajax/services/feed/load?v=1.0&callback=?&scoring=h&num=-1&q=' + processURL(url),
+ function (data, status) {
+ if (!data.responseData) {
+ complete('');
+ return;
+ }
+ beforeComplete(data.responseData.feed.title);
+ var text = [];
+ data.responseData.feed.entries.forEach(
+ function (entry) {
+ text.push(processText(entry.title));
+ text.push(processText(entry.content).replace(/<[^>]+?>|\(.+?\.\.\.\)|\&\w+\;|<script.+?\/script\>/ig, ''));
+ }
+ );
+ text = text.join('\n');
+ setTimeout(
+ function () {
+ complete(text);
+ },
+ 0
+ );
+ }
+ );
+ };
+
+ function getHTMLText(url, processText, beforeComplete, complete) {
+ $.getJSON(
+ 'http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20html%20where%20url%3D%22' + processURL(url) + '%22&format=json&diagnostics=true&callback=?',
+ function (data, status) {
+ if (!data.query.results) {
+ complete('');
+ return;
+ }
+ beforeComplete();
+ var text = [];
+
+ function parseElementObject(obj) {
+ // TBD, properly exclude script
+ for (var key in obj) if (obj.hasOwnProperty(key)) {
+ if (key === 'script' || key === 'style') continue;
+ else if (key === 'content') text.push(obj[key]);
+ else if (typeof obj[key] === 'object' && key !== 'script' && key !== 'style') parseElementObject(obj[key]);
+ }
+ }
+
+ parseElementObject(data.query.results);
+ text = text.join('\n');
+ setTimeout(
+ function () {
+ complete(text);
+ },
+ 0
+ );
+ }
+ );
+ }
+
+ function getFileContent(files, processText, beforeComplete, complete) {
+ var text = '', i = files.length - 1;
+ function handleFile() {
+ var reader = new FileReader(),
+ file = files[i];
+ reader.onloadend = function (ev) {
+ text += processText(ev.target.result.replace(/<[^>]+?>/g, ''));
+ if (!i--) {
+ setTimeout(
+ function () {
+ complete(processText(ev.target.result.replace(/<[^>]+?>|<script.+?\/script\>/ig, '')));
+ },
+ 0
+ );
+ } else {
+ handleFile();
+ }
+ }
+ reader.onerror = function () {
+ if (!i--) {
+ setTimeout(
+ function () {
+ complete(text);
+ },
+ 0
+ );
+ } else {
+ handleFile();
+ }
+ };
+ reader.readAsText(file, $('#encoding').val());
+ };
+ beforeComplete();
+ handleFile();
+ }
+
+ // helper function
+
+ function processURL(url) {
+ if (url.indexOf('%') !== -1) {
+ return encodeURIComponent(decodeURI(url));
+ } else {
+ return encodeURIComponent(url);
+ }
+ }
+
+ function updateTitle(type, title) {
+ $('#title')
+ .empty()
+ .append('<span class="famfamfam_sprite ' + {feed:'feed', html:'drive_world', file:'drive'}[type] + '"></span>')
+ .append($('<span />').text(t('title', title)));
+ }
+
+ function processingFeed(title) {
+ if (title) updateTitle('feed', title);
+ changeUIState.loading(t('processing'));
+ };
+
+ function processingHTML(title) {
+ if (title) updateTitle('html', data.responseData.feed.title);
+ changeUIState.loading(t('processing'));
+ };
+
+ function readingFile() {
+ changeUIState.loading(t('reading'));
+ };
+
+ // handleText
+
+ function handleText (text) {
+ changeUIState.loading(t('analyzing'));
+ if (!text) {
+ changeUIState.error(t('errorReading'));
+ return;
+ }
+ wordfreq.empty();
+ wordfreq.processText(
+ text,
+ function () {
+ changeUIState.ready();
+
+ list = wordfreq.getSortedList();
+
+ if (list.length < 5) {
+ changeUIState.error(t('errorWordCount'));
+ return;
+ }
+
+ weightFactor = $c[0].offsetHeight * $c[0].offsetWidth / list[0][1] / 3500;
+ gridSize = 8;
+
+ var wordLength = list.length.toString(10),
+ maxCount = list[0][1].toString(10);
+
+
+ $c.wordCloud({
+ wordColor: theme[themeid].wordColor,
+ backgroundColor: theme[themeid].backgroundColor,
+ fontFamily: theme[themeid].fontFamily,
+ wordList: [
+ [t('readyList_1', wordLength, maxCount), t('readyList_1C')],
+ [t('readyList_2', wordLength, maxCount), t('readyList_2C')],
+ [t('readyList_3', wordLength, maxCount), t('readyList_3C')],
+ [t('readyList_4', wordLength, maxCount), t('readyList_4C')]
+ ],
+ abortThreshold: 200,
+ abort: changeUIState.too_slow
+ });
+ }
+ );
+ };
+
+ // panel functions
+
+ $('.smaller').bind(
+ 'click',
+ function () {
+ weightFactor -= 0.1;
+ changeUIState.draw();
+ return false;
+ }
+ );
+
+
+ $('.larger').bind(
+ 'click',
+ function () {
+ weightFactor += 0.1;
+ changeUIState.draw();
+ return false;
+ }
+ );
+
+ $('.changetheme').bind(
+ 'click',
+ function () {
+ themeid++;
+ if (themeid >= theme.length) themeid = 0;
+ $(document.body).css('background-color', theme[themeid].backgroundColor);
+ changeUIState.draw();
+ return false;
+ }
+ );
+
+ $('.thiner').bind(
+ 'click',
+ function () {
+ gridSize --;
+ changeUIState.draw();
+ return false;
+ }
+ );
+
+ $('.thicker').bind(
+ 'click',
+ function () {
+ gridSize ++;
+ changeUIState.draw();
+ return false;
+ }
+ );
+
+ $('.save').bind(
+ 'click',
+ function () {
+ window.open($c[0].toDataURL());
+ return false;
+ }
+ );
+});
108 wordfreq.js
@@ -0,0 +1,108 @@
+
+
+//"use strict";
+
+var WordFreq = function (settings) {
+
+ if (!WordFreq.supported) return false;
+
+ var worker,
+ options = {
+ root: '',
+ processCJK: true,
+ processEnglish: true,
+ de_commword: true,
+ de_repetition: true,
+ unigram: false,
+ bigram: true,
+ trigram: true,
+ four_gram: true,
+ five_gram: true,
+ six_gram: true,
+ mincount: 3
+ },
+ words = {},
+ reps = {},
+ processText = function (text, callback) {
+ worker.onmessage = function (ev) {
+ for (var word in ev.data.words) if (ev.data.words.hasOwnProperty(word)) {
+ if (!words[word]) words[word] = ev.data.words[word];
+ else words[word] += ev.data.words[word];
+ if (ev.data.reps[word]) {
+ if (!reps[word]) reps[word] = ev.data.reps[word];
+ // else TBD
+ }
+ };
+ callback.apply(this, [ev.data.words]);
+ };
+ worker.postMessage(
+ {
+ settings: settings,
+ text: text
+ }
+ );
+ },
+ terminate = function () {
+ worker.terminate();
+ },
+ empty = function () {
+ words = {};
+ reps = {};
+ },
+ getList = function () {
+ var list = [];
+ for (var word in words) if (words.hasOwnProperty(word)) {
+ if (words[word] < settings.mincount) continue;
+ if (reps[word]) {
+ var maxRep, c = 0;
+ if (typeof reps[word].hasOwnProperty !== 'function') {
+ maxRep = 'hasOwnProperty'; // this happened to a JS blog ...
+ } else {
+ for (var rep in reps[word]) if (reps[word].hasOwnProperty(rep)) {
+ if (reps[word][rep] > c) maxRep = rep;
+ }
+ }
+ }
+ list.push([maxRep || word, words[word]]);
+ }
+ return list;
+ },
+ getSortedList = function () {
+ return getList().sort(
+ function (a, b) {
+ if (a[1] > b[1]) return -1;
+ if (a[1] < b[1]) return 1;
+ var t = [a[0], b[0]];
+ t = t.sort();
+ if (t[0] !== a[0]) return 1;
+ return 0;
+ }
+ );
+ },
+ analyizeVolume = function () {
+ var v = 0;
+ for (var word in words) if (words.hasOwnProperty(word)) {
+ if (words[word] < settings.mincount) continue;
+ v += word.length*words[word]*words[word];
+ }
+ return v;
+ };
+
+ if (!settings) settings = {};
+ for (var opt in options) if (options.hasOwnProperty(opt)) {
+ if (typeof settings[opt] === 'undefined') settings[opt] = options[opt];
+ }
+
+ worker = new Worker(settings.root + 'wordfreq.worker.js');
+
+ return {
+ processText: processText,
+ terminate: terminate,
+ empty: empty,
+ getList: getList,
+ getSortedList: getSortedList,
+ analyizeVolume: analyizeVolume
+ };
+};
+
+WordFreq.supported = (window.Worker && Array.prototype.push && Array.prototype.indexOf);
101 wordfreq.worker.js
@@ -0,0 +1,101 @@
+
+"use strict";
+
+// http://tartarus.org/~martin/PorterStemmer/js.txt
+// Porter stemmer in Javascript
+// Release 1 be 'andargor', Jul 2004
+// Release 2 (substantially revised) by Christopher McKenzie, Aug 2009
+var stemmer=function(){var g={ational:"ate",tional:"tion",enci:"ence",anci:"ance",izer:"ize",bli:"ble",alli:"al",entli:"ent",eli:"e",ousli:"ous",ization:"ize",ation:"ate",ator:"ate",alism:"al",iveness:"ive",fulness:"ful",ousness:"ous",aliti:"al",iviti:"ive",biliti:"ble",logi:"log"},h={icate:"ic",ative:"",alize:"al",iciti:"ic",ical:"ic",ful:"",ness:""};return function(a){var d,b,e,c,f;if(a.length<3)return a;e=a.substr(0,1);if(e=="y")a=e.toUpperCase()+a.substr(1);c=/^(.+?)(ss|i)es$/;b=/^(.+?)([^s])s$/; if(c.test(a))a=a.replace(c,"$1$2");else if(b.test(a))a=a.replace(b,"$1$2");c=/^(.+?)eed$/;b=/^(.+?)(ed|ing)$/;if(c.test(a)){b=c.exec(a);c=/^([^aeiou][^aeiouy]*)?[aeiouy][aeiou]*[^aeiou][^aeiouy]*/;if(c.test(b[1])){c=/.$/;a=a.replace(c,"")}}else if(b.test(a)){b=b.exec(a);d=b[1];b=/^([^aeiou][^aeiouy]*)?[aeiouy]/;if(b.test(d)){a=d;b=/(at|bl|iz)$/;f=/([^aeiouylsz])\1$/;d=/^[^aeiou][^aeiouy]*[aeiouy][^aeiouwxy]$/;if(b.test(a))a+="e";else if(f.test(a)){c=/.$/;a=a.replace(c,"")}else if(d.test(a))a+="e"}}c= /^(.+?)y$/;if(c.test(a)){b=c.exec(a);d=b[1];c=/^([^aeiou][^aeiouy]*)?[aeiouy]/;if(c.test(d))a=d+"i"}c=/^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/;if(c.test(a)){b=c.exec(a);d=b[1];b=b[2];c=/^([^aeiou][^aeiouy]*)?[aeiouy][aeiou]*[^aeiou][^aeiouy]*/;if(c.test(d))a=d+g[b]}c=/^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/;if(c.test(a)){b=c.exec(a);d=b[1];b=b[2];c=/^([^aeiou][^aeiouy]*)?[aeiouy][aeiou]*[^aeiou][^aeiouy]*/; if(c.test(d))a=d+h[b]}c=/^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/;b=/^(.+?)(s|t)(ion)$/;if(c.test(a)){b=c.exec(a);d=b[1];c=/^([^aeiou][^aeiouy]*)?[aeiouy][aeiou]*[^aeiou][^aeiouy]*[aeiouy][aeiou]*[^aeiou][^aeiouy]*/;if(c.test(d))a=d}else if(b.test(a)){b=b.exec(a);d=b[1]+b[2];b=/^([^aeiou][^aeiouy]*)?[aeiouy][aeiou]*[^aeiou][^aeiouy]*[aeiouy][aeiou]*[^aeiou][^aeiouy]*/;if(b.test(d))a=d}c=/^(.+?)e$/;if(c.test(a)){b=c.exec(a);d=b[1];c=/^([^aeiou][^aeiouy]*)?[aeiouy][aeiou]*[^aeiou][^aeiouy]*[aeiouy][aeiou]*[^aeiou][^aeiouy]*/; b=/^([^aeiou][^aeiouy]*)?[aeiouy][aeiou]*[^aeiou][^aeiouy]*([aeiouy][aeiou]*)?$/;f=/^[^aeiou][^aeiouy]*[aeiouy][^aeiouwxy]$/;if(c.test(d)||b.test(d)&&!f.test(d))a=d}c=/ll$/;b=/^([^aeiou][^aeiouy]*)?[aeiouy][aeiou]*[^aeiou][^aeiouy]*[aeiouy][aeiou]*[^aeiou][^aeiouy]*/;if(c.test(a)&&b.test(a)){c=/.$/;a=a.replace(c,"")}if(e=="y")a=e.toLowerCase()+a.substr(1);return a}}();
+
+// English stopwords that is being filtered out by Google
+// http://www.ranks.nl/resources/stopwords.html (the shortest list)
+var englishStopWords = [
+ 'i','a','about',
+ 'an','and','are','as','at',
+ 'be','by','com','for',
+ 'from','how','in',
+ 'is','it','not',
+ 'of','on','or','that',
+ 'the','this','to','was',
+ 'what','when','where',
+ 'who','will','with',
+ 'www','the'
+];
+
+onmessage = function (ev) {
+ var words = {},
+ reps = {},
+ settings = ev.data.settings,
+ text = ev.data.text;
+
+ function handleWord (word, rep) {
+ if (!words[word]) words[word] = 1;
+ else words[word]++;
+ if (rep) {
+ if (!reps[word]) reps[word] = {};
+ if (!reps[word][rep]) reps[word][rep] = 1;
+ else reps[word][rep]++;
+ }
+ }
+
+ function processCJK (text) {
+ if (settings.de_commword) {
+ text = text.replace(/\u7684/g, '\n');
+ }
+
+ // TBD: Cannot match CJK characters beyond BMP, e.g. \u20000-\u2A6DF at plane B.
+ text = text.replace(/[^\u4E00-\u9FFF\u3400-\u4DBF]+/gm, '\n');
+
+ var reg = /./g,
+ reuni = /^.$/,
+ rebi = /^.{2}$/,
+ re3 = /^.{3}$/,
+ re4 = /^.{4}$/,
+ re5 = /^.{5}$/;
+
+ text.replace(
+ reg,
+ function (str, offset, text) {
+ if (settings.unigram) handleWord(str);
+ if (settings.bigram && reuni.test(text[offset+1])) handleWord(str + text[offset+1]);
+ if (settings.trigram && rebi.test(text.substr(offset+1, 2))) handleWord(str + text.substr(offset+1, 2));
+ if (settings.four_gram && re3.test(text.substr(offset+1, 3))) handleWord(str + text.substr(offset+1, 3));
+ if (settings.five_gram && re4.test(text.substr(offset+1, 4))) handleWord(str + text.substr(offset+1, 4));
+ if (settings.six_gram && re5.test(text.substr(offset+1, 5))) handleWord(str + text.substr(offset+1, 5));
+ }
+ );
+
+ if (settings.de_repetition) {
+ // Not doing hasOwnProperty() coz this is a standalone worker js
+ for (var word in words) /* if (words.hasOwnProperty(word)) */ {
+ if (word.length === 1) return;
+ var l = word.length-1;
+ while (l) {
+ var i = word.length-l;
+ while (i >= 0) {
+ var substr = word.substr(i, l);
+ if (words[substr] && words[substr] === words[word]) words[substr] = -1;
+ i--;
+ }
+ l--;
+ }
+ }
+ }
+ }
+
+ function processEnglish(text) {
+ text.replace(/[^A-Za-zéÉ'’]+/gm, '\n').replace(/['’](s|ll|d)\b/g, '').split('\n').forEach(
+ function (word) {
+ if (!word) return;
+ if (word.length < 2) return;
+ if (settings.de_commword && englishStopWords.indexOf(word.toLowerCase()) !== -1) return;
+ handleWord(stemmer(word).toLowerCase(), word);
+ }
+ );
+ }
+
+ if (settings.processCJK) processCJK(text);
+ if (settings.processEnglish) processEnglish(text);
+
+ postMessage({words:words, reps:reps});
+};
167 zh/index.html
@@ -0,0 +1,167 @@
+<!DOCTYPE html>
+<html lang="zh-TW">
+<head>
+<meta charset=UTF-8>
+<title>HTML5 文字雲:文章詞彙分析機</title>
+<link rel="stylesheet" type="text/css" href="../wordcloud.css" />
+</head>
+<body>
+<canvas id="canvas" class="toggleUI"></canvas>
+<div id="loading" class="center_msg">
+ <p>載入中 ...</p>
+</div>
+<div id="error" class="error toggleUI center_msg">
+ <p>&nbsp;</p>
+ <a href="#" class="start">再試一次</a>
+</div>
+<div id="too_slow" class="error toggleUI center_msg">
+ <p>您的瀏覽器效能太慢,請改用其他瀏覽器(部分電腦的 Firefox 會有此問題)</p>
+</div>
+<div id="not_support" class="error toggleUI center_msg">
+ <p>您的瀏覽器缺少必要的功能。</p>
+ <p>請升級,或是改用支援 HTML5 相關功能的瀏覽器:</p>
+ <ul>
+ <li><a href="http://moztw.org/" target="_blank">Firefox</a></li>
+ <li><a href="http://www.apple.com/tw/safari/" target="_blank">Safari</a></li>
+ <li><a href="http://www.google.com/chrome/" target="_blank">Chrome</a></li>
+ <li><a href="http://www.opera.com/" target="_blank">Opera</a></li>
+ </ul>
+</div>
+<noscript>
+<div class="center_msg">
+ <p>請開啟瀏覽器的 JavaScript。</p>
+</div>
+</noscript>
+<p id="title" class="toggleUI"></p>
+<a id="start" href="#" class="toggleUI start center_btn">文字雲 - 按這裡開始</a>
+<a id="ready" href="#" class="toggleUI ready center_btn">準備完成</a>
+<div id="controls" class="toggleUI left_tool">
+ <ul>
+ <li><a href="#" class="changetheme"><span class="famfamfam_sprite color_wheel"></span>切換色系</a></li>
+ <li><a href="#" class="larger"><span class="famfamfam_sprite comment"></span>放大文字</a></li>
+ <li><a href="#" class="smaller"><span class="famfamfam_sprite comments"></span>縮小文字</a></li>
+ <!-- disable to novice user
+ <li><a href="#" class="thicker"><span class="famfamfam_sprite arrow_out"></span>增大間距</a></li>
+ <li><a href="#" class="thiner"><span class="famfamfam_sprite arrow_in"></span>縮小間距</a></li>
+ -->
+ <li><a href="#" class="ready"><span class="famfamfam_sprite arrow_refresh"></span>重新排列</a></li>
+ <li><a href="#" class="save"><span class="famfamfam_sprite disk"></span>儲存圖片</a></li>
+ </ul>
+</div>
+<div id="help" class="left_tool">
+ <ul>
+ <li><a href="#" class="start"><span class="famfamfam_sprite arrow_undo"></span>重來</a></li>
+ <li><a href="#" class="help"><span class="famfamfam_sprite help"></span>關於</a></li>
+ </ul>
+</div>
+<div id="language" class="left_tool">
+ <ul>
+ <li><a href="../en/">English</a></li>
+ <li><strong>正體中文</strong></li>
+ </ul>
+</div>
+<div id="source_panel" class="toggleUI panel">
+ <h2>詞彙分析文字來源</h2>
+ <form id="source_panel_form" action="#" method="post">
+ <p class="menu panel_left">
+ <label class="generic"><span class="famfamfam_sprite award_star_bronze_1"></span><input type="radio" name="source" value="demo" checked /> 範例資料</label>
+ <label class="generic"><span class="famfamfam_sprite feed"></span><input type="radio" name="source" value="feed" /> RSS Feed</label>
+ <!--<label class="generic"><span class="famfamfam_sprite page_world"></span><input type="radio" name="source" value="html" /> 網頁</label>-->
+ <label class="generic"><span class="famfamfam_sprite disk"></span><input type="radio" name="source" value="file" /> 硬碟裡的檔案</label>
+ <!--<label><input type="radio" name="source" value="wiki" /> 中文維基百科</label>-->
+ <label><input type="radio" name="source" value="blog:blogger" /> Blogger</label>
+ <label><input type="radio" name="source" value="blog:pixnet"/> 痞客邦部落格</label>
+ <label><input type="radio" name="source" value="blog:wretch"/> 無名小站部落格</label>
+ <label><input type="radio" name="source" value="blog:plurk"/> 噗浪</label>
+ <label><input type="radio" name="source" value="blog:twitter"/> Twitter</label>
+ </p>
+ <hr />
+ <div id="demo_entry" class="entry">
+ <p>分析來源範例</p>
+ <p class="menu">
+ <label><input type="radio" name="demo" value="feed:http://www.president.gov.tw/RSS.aspx?tabid=1104&amp;moduleid=2074" checked /> 馬英九總統治國週記 </label>
+ <!--<label><input type="radio" name="demo" value="html:http://zh.wikipedia.org/zh-tw/台灣" /> 中文維基百科「台灣」條目 <a href="http://zh.wikipedia.org/zh-tw/%E5%8F%B0%E7%81%A3" target="_blank" class="link famfamfam_sprite application_double">link</a></label>-->
+ <label><input type="radio" name="demo" value="feed:http://et.e-info.org.tw/rss.xml" /> 環境信託「全民來認股 守護白海豚」網站 <a href="http://et.e-info.org.tw/" target="_blank" class="link famfamfam_sprite application_double">link</a></label>
+ <label><input type="radio" name="demo" value="feed:http://sophist4ever.pixnet.net/blog/feed/rss" /> 假圖天國 <a href="http://sophist4ever.pixnet.net/blog" target="_blank" class="link famfamfam_sprite application_double">link</a></label>
+ <label><input type="radio" name="demo" value="feed:http://richter.pixnet.net/blog/feed/rss" /> 地圖會說話 <a href="http://richter.pixnet.net/blog" target="_blank" class="link famfamfam_sprite application_double">link</a></label>
+ <label><input type="radio" name="demo" value="feed:http://playpcesor.blogspot.com/feeds/posts/default" /> 電腦玩物 <a href="http://playpcesor.blogspot.com/" target="_blank" class="link famfamfam_sprite application_double">link</a></label>
+ <label><input type="radio" name="demo" value="feed:http://www.president.gov.tw/RSS.aspx?tabid=131&amp;moduleid=514" /> 總統府新聞稿</label>
+ </p>
+ </div>
+ <div id="blog_entry" class="entry">
+ <p><label><span><span class="feed_type_name"></span>帳號 ID:</span><input type="text" size="14" id="username" /></label></p>
+ <p>某些網站沒有提供全文 RSS,僅能處理可抓到的部份。</p>
+ </div>
+ <div id="feed_entry" class="entry">
+ <p><label><span>RSS 網址:</span><input type="url" size="40" id="rss" /></label></p>
+ <p>未曾被訂閱過的 RSS 無法取得。</p>
+ </div>
+ <div id="file_entry" class="entry">
+ <p><label><span>選擇檔案:</span><input type="file" id="file" multiple /></label></p>
+ <p><label><span>編碼:</span><input type="text" size="10" id="encoding" value="UTF-8" /></label></p>
+ <p>檔案會直接處理,不會被上傳。</p>
+ </div>
+ <div id="wiki_entry" class="entry">
+ <p><label><span>條目:</span><input type="text" size="14" id="wikipedia_entry" /></label></p>
+ </div>
+ <div id="html_entry" class="entry">
+ <p><label><span>網址:</span><input type="url" size="40" id="html_url" /></label></p>
+ <p>僅能處理被搜尋引擎分析過的公開網頁。</p>
+ </div>
+ <button type="submit" id="source_panel_finish">開始</button>
+ </form>
+</div>
+<div id="help_panel" class="panel">
+ <h2>關於</h2>
+ <div class="entry">
+ <p>作者:<a href="http://timc.idv.tw/" target="_blank">timdream</a>。任何建議歡迎<a href="http://blog.timc.idv.tw/posts/wordcloud/" target="_blank">留言</a>。</p>
+ <p>使用技術:</p>
+ <ul>
+ <li>中文:自製的 N-gram 演算法</li>
+ <li>英文:<a href="http://tartarus.org/~martin/PorterStemmer/" target="_blank">Porter Stemming Algorithm</a></li>
+ <li>HTML5 canvas</li>
+ <li>HTML5 FileReader API</li>
+ <li>HTML5 Web Workers API</li>
+ <li>Javascript 1.6 <a href="https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array" target="_blank">新 Array 函式</a></li>
+ </ul>
+ <p>資料提供:</p>
+ <ul>
+ <li><a href="https://code.google.com/apis/feed/" target="_blank">Google Feed API</a></li>
+ <!--<li><a href="http://developer.yahoo.com/yql/" target="_blank">YQL API</a></li>-->
+ </ul>
+ <button>關閉</button>
+ </div>
+</div>
+<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.5/jquery.min.js"></script>
+<script type="text/javascript" src="../jquery.wordcloud.js"></script>
+<script type="text/javascript" src="../wordfreq.js"></script>
+<script type="text/javascript" src="../wordcloud.js"></script>
+<script type="text/javascript">
+var T = {
+ title: '$1 的文字雲',
+ downloading: '下載中 ...',
+ reading: '讀取中 ...',
+ processing: '處理中 ...',
+ analyzing: '分析中 ...',
+ errorReading: '讀取失敗,請稍後再試。',
+ errorWordCount: '取得詞彙數量太少,請選其他內容。',
+ startList_1: 'HTML5 文字雲',
+ startList_1C: 60,
+ startList_2: 'Word Cloud',
+ startList_2C: 35,
+ startList_3: '文章詞彙分析機',
+ startList_3C: 40,
+ startList_4: '點選後開始',
+ startList_4C: 26,
+ readyList_1: '詞彙分析完成',
+ readyList_1C: 45,
+ readyList_2: '共 $1 詞',
+ readyList_2C: 26,
+ readyList_3: '最多重複 $2 次',
+ readyList_3C: 20,
+ readyList_4: '點選後開始',
+ readyList_4C: 17
+};
+</script>
+</body>
+</html>
Please sign in to comment.
Something went wrong with that request. Please try again.