PageRenderTime 28ms CodeModel.GetById 14ms RepoModel.GetById 1ms app.codeStats 0ms

/nebulos.js

https://github.com/esimionato/google-plus-me
JavaScript | 546 lines | 500 code | 18 blank | 28 comment | 51 complexity | 48f227dfeb41269e8c3ee980972da607 MD5 | raw file
  1. /* r11 from http://code.google.com/p/nebulos/source/browse/trunk/%20nebulos%20--username%20leforthomas/nebulos/src/nebulos.js */
  2. var metaaps = {};
  3. metaaps.nebulos = function(container, width, height) {
  4. this.container = container;
  5. // huyz 2011-09-18
  6. //var width = container.width;
  7. //var height = container.height;
  8. width = width || container.width || container.style.width;
  9. height = height || container.height || container.style.height;
  10. this.canvas = canvasport.createCanvas(container, width, height, {"margin":"0px", "padding":"0px", "border":"none"});
  11. // huyz 2011-09-18
  12. //this.opacityvalue = 0.9;
  13. this.opacityvalue = 1;
  14. this.notestboxes = true;
  15. this.stroke = true;
  16. // huyz 2011-09-18
  17. //this.screenportion = 0.3;
  18. this.screenportion = 0.6;
  19. this.fillstyle = {red: 0, green: 0, blue: 0};
  20. this.strokestyle = "rgba(0, 0, 0, 0.1)";;
  21. this.shaded = true;
  22. this.multicolor = false;
  23. this.boxes = [];
  24. this.running = false;
  25. this.restarthandler = null;
  26. this.directions = ['ne', 'se', 'nw', 'sw'];
  27. this.fontfamily = "serif";
  28. this.minWordSize = 3;
  29. // a default text list
  30. this.textlist = [{text: "Nebulos", weight: 30}, {text: "Cool", weight: 15}, {text: "Excellent", weight: 2}, {text: "Want It!", weight: 5}, {text: "Google", weight: 25}, {text: "Rules", weight: 15}, {text: "Visualisation", weight: 10}, {text: "Charts", weight: 10}];
  31. this.symbols = [
  32. '.',
  33. '!',
  34. ':',
  35. '*',
  36. '?',
  37. '+',
  38. '\'',
  39. '\"',
  40. ',',
  41. ';',
  42. '#',
  43. '%',
  44. '&',
  45. '/',
  46. '=',
  47. '[',
  48. ']',
  49. '{',
  50. '}',
  51. '- ',
  52. '_',
  53. '(',
  54. ')',
  55. '\r',
  56. '\t',
  57. '\n'
  58. ];
  59. this.commonwords = [
  60. 'the',
  61. 'of',
  62. 'to',
  63. 'and',
  64. 'a',
  65. 'in',
  66. 'is',
  67. 'it',
  68. 'you',
  69. 'that',
  70. 'he',
  71. 'was',
  72. 'for',
  73. 'on',
  74. 'are',
  75. 'with',
  76. 'as',
  77. 'i',
  78. 'his',
  79. 'they',
  80. 'be',
  81. 'at',
  82. 'one',
  83. 'have',
  84. 'this',
  85. 'from',
  86. 'or',
  87. 'had',
  88. 'by',
  89. 'hot',
  90. 'word',
  91. 'but',
  92. 'what',
  93. 'some',
  94. 'we',
  95. 'can',
  96. 'out',
  97. 'other',
  98. 'were',
  99. 'all',
  100. 'there',
  101. 'when',
  102. 'up',
  103. 'use',
  104. 'your',
  105. 'how',
  106. 'said',
  107. 'an',
  108. 'each',
  109. 'she',
  110. 'which',
  111. 'do',
  112. 'their',
  113. 'time',
  114. 'if',
  115. 'will',
  116. 'way',
  117. 'about',
  118. 'many',
  119. 'then',
  120. 'them',
  121. 'write',
  122. 'don',
  123. 'doesn',
  124. 'didn',
  125. 'would',
  126. 'wouldn',
  127. 'like',
  128. 'so',
  129. 'these',
  130. 'her',
  131. 'long',
  132. 'thing',
  133. 'see',
  134. 'him',
  135. 'two',
  136. 'has',
  137. 'look',
  138. 'more',
  139. 'day',
  140. 'could',
  141. 'go',
  142. 'come',
  143. 'did',
  144. 'no',
  145. 'most',
  146. 'my',
  147. 'over',
  148. 'than',
  149. 'who',
  150. 'may',
  151. 'down',
  152. 'been',
  153. 'any',
  154. 'not',
  155. // huyz 2011-09-18
  156. 'just',
  157. 'avec',
  158. 'pour',
  159. 'nous',
  160. 'vous',
  161. 'notre',
  162. 'votre',
  163. 'cet',
  164. 'cette',
  165. 'tout',
  166. 'dans',
  167. 'toi',
  168. 'les',
  169. 'sans',
  170. 'mais',
  171. 'leur',
  172. // huyz 2011-09-18 http://johannburkard.de/resources/Johann/jquery.dynacloud-5.js
  173. "a", "about", "above", "accordingly", "after",
  174. "again", "against", "ah", "all", "also", "although", "always", "am", "among", "amongst", "an",
  175. "and", "any", "anymore", "anyone", "are", "as", "at", "away", "be", "been",
  176. "begin", "beginning", "beginnings", "begins", "begone", "begun", "being",
  177. "below", "between", "but", "by", "ca", "can", "cannot", "come", "could",
  178. "did", "do", "doing", "during", "each", "either", "else", "end", "et",
  179. "etc", "even", "ever", "far", "ff", "following", "for", "from", "further", "furthermore",
  180. "get", "go", "goes", "going", "got", "had", "has", "have", "he", "her",
  181. "hers", "herself", "him", "himself", "his", "how", "i", "if", "in", "into",
  182. "is", "it", "its", "itself", "last", "lastly", "less", "many", "may", "me",
  183. "might", "more", "must", "my", "myself", "near", "nearly", "never", "new",
  184. "next", "no", "not", "now", "o", "of", "off", "often", "oh", "on", "only",
  185. "or", "other", "otherwise", "our", "ourselves", "out", "over", "perhaps",
  186. "put", "puts", "quite", "s", "said", "saw", "say", "see", "seen", "shall",
  187. "she", "should", "since", "so", "some", "such", "t", "than", "that", "the",
  188. "their", "them", "themselves", "then", "there", "therefore", "these", "they",
  189. "this", "those", "though", "throughout", "thus", "to", "too",
  190. "toward", "unless", "until", "up", "upon", "us", "ve", "very", "was", "we",
  191. "were", "what", "whatever", "when", "where", "which", "while", "who",
  192. "whom", "whomever", "whose", "why", "with", "within", "without", "would",
  193. "yes", "your", "yours", "yourself", "yourselves"
  194. ];
  195. this.measureText = function(text, fontSize, vertical, ctx) {
  196. if(vertical)
  197. {
  198. return {height: canvasport.measureText(ctx, text), width: fontSize};
  199. } else {
  200. return {width: canvasport.measureText(ctx, text), height: fontSize};
  201. }
  202. }
  203. this.findPosition = function(startpos, box, vertical, directionnumber, ctx) {
  204. // slide in direction until possible to fit box in image
  205. for(var count = 0; count < 150; count+=3)
  206. {
  207. var direction = this.directions[directionnumber%this.directions.length];
  208. var pos = this.getPosition(startpos, direction, count);
  209. if(ctx.getImageData && this.notestboxes)
  210. {
  211. if(canvasport.hitTest(ctx, pos.x, (vertical ? pos.y - box.height : pos.y), box.width, box.height, true) == false)
  212. {
  213. return pos;
  214. }
  215. } else {
  216. var curbox = {x: pos.x, y: (vertical ? pos.y - box.height : pos.y), width: box.width, height: box.height};
  217. // scan boxes instead
  218. for(var index = 0; index < this.boxes.length; index++)
  219. {
  220. var existingbox = this.boxes[index];
  221. if(existingbox.x < curbox.x + curbox.width
  222. && curbox.x < existingbox.x + existingbox.width
  223. && existingbox.y < curbox.y + curbox.height
  224. && curbox.y < existingbox.y + existingbox.height)
  225. {
  226. break;
  227. }
  228. }
  229. if(index == this.boxes.length)
  230. {
  231. return pos;
  232. }
  233. }
  234. directionnumber++;
  235. }
  236. return null;
  237. }
  238. this.getPosition = function(startpos, direction, count) {
  239. var pos = startpos;
  240. switch(direction)
  241. {
  242. case 'n':
  243. {
  244. pos.y -= count;
  245. }break;
  246. case 's':
  247. {
  248. pos.y += count;
  249. }break;
  250. case 'e':
  251. {
  252. pos.x += count;
  253. }break;
  254. case 'w':
  255. {
  256. pos.x -= count;
  257. }break;
  258. case 'ne':
  259. {
  260. pos.y -= count;
  261. pos.x += count;
  262. }break;
  263. case 'se':
  264. {
  265. pos.y += count;
  266. pos.x += count;
  267. }break;
  268. case 'nw':
  269. {
  270. pos.y -= count;
  271. pos.x -= count;
  272. }break;
  273. case 'sw':
  274. {
  275. pos.y += count;
  276. pos.x -= count;
  277. }break;
  278. }
  279. return pos;
  280. }
  281. this.extendBounds = function(bounds, box) {
  282. bounds.minx = Math.min(box.x, bounds.minx);
  283. bounds.miny = Math.min(box.y, bounds.miny);
  284. bounds.maxx = Math.max(box.x + box.width, bounds.maxx);
  285. bounds.maxy = Math.max(box.y + box.height, bounds.maxy);
  286. }
  287. this.drawText = function(text, font, position, vertical, ctx) {
  288. canvasport.drawText(ctx, text, position.x, position.y, vertical, font, this.stroke);
  289. }
  290. this.getOpacityvalue = function(fontsize, maxfontsize) {
  291. if(this.shaded == false)
  292. {
  293. return this.opacityvalue;
  294. } else {
  295. return fontsize / maxfontsize * 0.6 + 0.3;
  296. }
  297. }
  298. }
  299. // public methods
  300. metaaps.nebulos.prototype = {
  301. // call to change the default symbols used to filter a text
  302. setSymbols: function(symbols) {
  303. this.symbols = symbols;
  304. },
  305. // call to change the common words of a language used to filter a text
  306. changeMostCommonWords: function(commonWords) {
  307. this.commonwords = commonWords;
  308. },
  309. // call to change the filter, eg any word of minWordSize or less letters will not be displayed
  310. setMinWordSize: function(minWordSize) {
  311. this.minWordSize = minWordSize;
  312. },
  313. // interupts the current work and restart the drawing
  314. restart: function(callback)
  315. {
  316. this.restarthandler = callback;
  317. },
  318. // set the raw text, nebulos will extract the words and order them by order of importance
  319. setText: function(text) {
  320. this.textlist = this.generateTextlist(text);
  321. },
  322. // set the text list, as in any other word cloud widget format is [{text: "your text", weight: "the importance"}, ...]
  323. setTextList: function(textlist) {
  324. this.textlist = textlist;
  325. },
  326. setFontFamily: function(fontFamily) {
  327. this.fontfamily = fontFamily;
  328. },
  329. draw: function(data, options)
  330. {
  331. if(data) {
  332. if(typeof data == "string") {
  333. this.setText(data);
  334. } else {
  335. this.setTextList(data);
  336. }
  337. }
  338. this.boxes = [];
  339. this.running = true;
  340. this.restarthandler = null;
  341. var canvas = this.canvas;
  342. var ctx = canvasport.getDrawing(canvas);
  343. ctx.clearRect(0, 0, canvas.width, canvas.height);
  344. ctx.fillStyle = "rgba(255, 255, 255, 1)";
  345. ctx.fillRect(0, 0, canvas.width, canvas.height);
  346. var startpos = {x: canvas.width / 2, y: canvas.height / 2};
  347. var bounds = {minx: startpos.x, miny: startpos.y, maxx: startpos.x, maxy: startpos.y};
  348. function getStartpos(direction, box)
  349. {
  350. var boundscenter = {x: (bounds.maxx + bounds.minx) / 2, y: (bounds.maxy + bounds.miny) / 2};
  351. var startposition = {x: boundscenter.x - box.width / 2, y: (vertical ? boundscenter.y + box.height / 2 : boundscenter.y - box.height / 2)};
  352. var width = bounds.maxx - bounds.minx;
  353. var height = bounds.maxy - bounds.miny;
  354. // check which direction the bounding box is going
  355. var direction = "";
  356. if(boundscenter.y > startpos.y)
  357. {
  358. direction += 'n';
  359. } else {
  360. direction += 's';
  361. }
  362. if(boundscenter.x > startpos.x)
  363. {
  364. direction += 'w';
  365. } else {
  366. direction += 'e';
  367. }
  368. var shiftwidth = (Math.random()) * width / 3;
  369. var shiftheight = (Math.random()) * height / 3;
  370. switch(direction)
  371. {
  372. case 'ne':
  373. {
  374. return {x: startposition.x + shiftwidth, y: startposition.y - shiftheight};
  375. }break;
  376. case 'nw':
  377. {
  378. return {x: startposition.x - shiftwidth, y: startposition.y - shiftheight};
  379. }break;
  380. case 'se':
  381. {
  382. return {x: startposition.x + shiftwidth, y: startposition.y + shiftheight};
  383. }break;
  384. case 'sw':
  385. {
  386. return {x: startposition.x - shiftwidth, y: startposition.y + shiftheight};
  387. }break;
  388. }
  389. return null;
  390. }
  391. var directions = this.directions;
  392. var nebulos = this;
  393. var vertical = 0;
  394. this.textlistcount = 0;
  395. ctx.textBaseline = 'top';
  396. ctx.strokeStyle = this.strokestyle;
  397. ctx.textAlign = 'left';
  398. // measure all words first for font size
  399. var totalarea = {area: 0};
  400. // try with font factor at 10
  401. var fontincrease = 10;
  402. var textlist = this.textlist;
  403. for(var i = 0; i < textlist.length; i++) {
  404. var item = textlist[i];
  405. var fontSize = item.weight * fontincrease;
  406. ctx.font = fontSize + 'px ' + nebulos.fontfamily;
  407. var box = nebulos.measureText(item.text, fontSize, vertical, ctx);
  408. totalarea.area += box.width * box.height;
  409. }
  410. // recalculate fontincrease to have 20% of canvas used, assumes a square rule
  411. var fontfactor = Math.sqrt((canvas.width * canvas.height) / totalarea.area * nebulos.screenportion) * fontincrease;
  412. var maxfontsize = fontfactor * textlist[0].weight;
  413. var errormessage = "Could not place: ";
  414. function draw(){
  415. var textelement = textlist[nebulos.textlistcount++];
  416. var weight = textelement.weight;
  417. var fontSize = Math.floor(weight * fontfactor);
  418. ctx.font = fontSize + 'px ' + nebulos.fontfamily;
  419. ctx.textBaseline = 'top';
  420. var opacityvalue = nebulos.getOpacityvalue(fontSize, maxfontsize);
  421. ctx.fillStyle = "rgba(" + nebulos.fillstyle.red + ", " + nebulos.fillstyle.green + ", " + nebulos.fillstyle.blue + ", " + opacityvalue + ")";
  422. ctx.strokeStyle = nebulos.strokestyle;
  423. ctx.textAlign = 'left';
  424. var text = textelement.text;
  425. vertical = (Math.random() < 0.5);
  426. var box = nebulos.measureText(text, fontSize, vertical, ctx);
  427. try {
  428. for(var attempt = 0; attempt < 4; attempt++, vertical = !vertical, box = nebulos.measureText(text, fontSize, vertical, ctx))
  429. {
  430. var directionnumber = Math.floor(Math.random() * 4);
  431. var direction = directions[directionnumber];
  432. var position = nebulos.findPosition(getStartpos(direction, box), box, vertical, directionnumber, ctx);
  433. if(position != null)
  434. {
  435. nebulos.drawText(text, ctx.font, position, vertical, ctx);
  436. nebulos.boxes.push({x: position.x, y: (vertical ? position.y - box.height : position.y), width: box.width, height: box.height, position: position, text: text, vertical: vertical, font: ctx.font, fillstyle: ctx.fillstyle, fontSize: fontSize});
  437. break;
  438. }
  439. }
  440. if(attempt == 4)
  441. {
  442. errormessage += ' ' + text;
  443. }
  444. // extend the bounds
  445. nebulos.extendBounds(bounds, {x: position.x, y: (vertical ? position.y - box.height : position.y), width: box.width, height: box.height});
  446. } catch(e) {
  447. }
  448. if(nebulos.restarthandler != null)
  449. {
  450. setTimeout(function(){nebulos.restarthandler();}, 500);
  451. nebulos.running = false;
  452. return;
  453. }
  454. if(nebulos.textlistcount < textlist.length)
  455. {
  456. setTimeout(draw, 1);
  457. } else {
  458. nebulos.running = false;
  459. }
  460. }
  461. setTimeout(draw, 1);
  462. },
  463. redraw: function()
  464. {
  465. var canvas = this.canvas;
  466. var nebulos = this;
  467. var ctx = canvasport.getDrawing(canvas);
  468. ctx.clearRect(0, 0, canvas.width, canvas.height);
  469. ctx.textBaseline = 'top';
  470. ctx.strokeStyle = nebulos.strokestyle;
  471. ctx.textAlign = 'left';
  472. var maxfontsize = nebulos.boxes[0].fontSize;
  473. for(var i = 0; i < nebulos.boxes.length; i++) {
  474. var item = nebulos.boxes[i];
  475. var opacityvalue = nebulos.getOpacityvalue(item.fontSize, maxfontsize);
  476. ctx.fillStyle = "rgba(" + nebulos.fillstyle.red + ", " + nebulos.fillstyle.green + ", " + nebulos.fillstyle.blue + ", " + opacityvalue + ")";
  477. nebulos.drawText(item.text, item.font, item.position, item.vertical, ctx);
  478. }
  479. },
  480. generateTextlist: function(fulltext)
  481. {
  482. // build an array of words
  483. var wordslist = [];
  484. var newtext = fulltext + " ";
  485. newtext = newtext.toLowerCase();
  486. // remove common words from fulltext
  487. for(var i = 0; i < this.symbols.length; i++) {
  488. var item = this.symbols[i];
  489. newtext = newtext.replace(new RegExp('\\' + item, 'g'), " ");
  490. }
  491. for(var i = 0; i < this.commonwords.length; i++) {
  492. var item = this.commonwords[i];
  493. newtext = newtext.replace(new RegExp(" " + item + " ", 'g'), " ");
  494. }
  495. var textlist = newtext.split(" ");
  496. var words = {};
  497. var minwordsize = this.minWordSize;
  498. for(var i = 0; i < textlist.length; i++) {
  499. var item = textlist[i];
  500. if(item.length > minwordsize)
  501. {
  502. if(words[item])
  503. {
  504. words[item]++;
  505. } else {
  506. words[item] = 1;
  507. }
  508. }
  509. }
  510. for(var word in words)
  511. {
  512. if(!isNaN(words[word])) {
  513. wordslist.push({text: word, weight: words[word]});
  514. }
  515. }
  516. // order by weight
  517. function compare(a,b) {
  518. if (a.weight < b.weight)
  519. return 1;
  520. if (a.weight > b.weight)
  521. return -1;
  522. return 0;
  523. }
  524. wordslist.sort(compare);
  525. wordslist.splice(200, Math.max(0, wordslist.length - 200));
  526. return wordslist;
  527. }
  528. }