/*

DynaCloud v5

A dynamic JavaScript tag/keyword cloud with jQuery.

<http://johannburkard.de/blog/programming/javascript/dynacloud-a-dynamic-javascript-tag-keyword-cloud-with-jquery.html>

MIT license.

Johann Burkard
<http://johannburkard.de>
<mailto:jb@eaio.com>

*/

jQuery.fn.highlight = function(pat) {
 function innerHighlight(node, pat) {
  var skip = 0;
  if (node.nodeType == 3) {
   var pos = node.data.toUpperCase().indexOf(pat);
   if (pos >= 0) {
    var spannode = document.createElement('span');
    spannode.className = 'highlight';
    var middlebit = node.splitText(pos);
    var endbit = middlebit.splitText(pat.length);
    var middleclone = middlebit.cloneNode(true);
    spannode.appendChild(middleclone);
    middlebit.parentNode.replaceChild(spannode, middlebit);
    skip = 1;
   }
  }
  else if (node.nodeType == 1 && node.childNodes && !/(script|style)/i.test(node.tagName)) {
   for (var i = 0; i < node.childNodes.length; ++i) {
    i += innerHighlight(node.childNodes[i], pat);
   }
  }
  return skip;
 }
 return this.each(function() {
  innerHighlight(this, pat.toUpperCase());
 });
};

jQuery.fn.removeHighlight = function() {
 return this.find("span.highlight").each(function() {
  this.parentNode.firstChild.nodeName;
  with (this.parentNode) {
   replaceChild(this.firstChild, this);
   normalize();
  }
 }).end();
};

jQuery.dynaCloud = {

 max: 20,
 sort: true,
 auto: true,
 single: true,
 wordStats: true,
 scale: 4,

// Adapted from <http://www.perseus.tufts.edu/Texts/engstop.html>

 stopwords : [ "alors", "au", "aucuns", "aussi", "autre", "avant", "avec",
			"avoir", "bon", "car", "ce", "cela", "ces", "ceux", "chaque", "ci",
			"comme", "comment", "dans", "des", "du", "dedans", "dehors",
			"depuis", "deux", "devrait", "doit", "donc", "dos", "droite",
			"début", "elle", "elles", "en", "encore", "essai", "est", "et",
			"eu", "fait", "faites", "fois", "font", "force", "haut", "hors",
			"ici", "il", "ils", "je ", "la", "le", "les", "leur", "là", "ma",
			"maintenant", "mais", "mes", "mine", "moins", "mon", "mot", "même",
			"ni", "nommés", "notre", "nous", "nouveaux", "ou", "où", "par",
			"parce", "parole", "pas", "personnes", "peut", "peu", "pièce",
			"plupart", "pour", "pourquoi", "quand", "que", "quel", "quelle",
			"quelles", "quels", "qui", "sa", "sans", "ses", "seulement", "si",
			"sien", "son", "sont", "sous", "soyez", "sujet", "sur", "ta",
			"tandis", "tellement", "tels", "tes", "ton", "tous", "tout",
			"trop", "très", "tu", "valeur", "voie", "voient", "vont", "votre",
			"vous", "vu", "ça", "étaient", "état", "étions", "été", "être",
			"ALORS", "AU", "AUCUNS", "AUSSI", "AUTRE", "AVANT", "AVEC",
			"AVOIR", "BON", "CAR", "CE", "CELA", "CES", "CEUX", "CHAQUE", "CI",
			"COMME", "COMMENT", "DANS", "DES", "DU", "DEDANS", "DEHORS",
			"DEPUIS", "DEUX", "DEVRAIT", "DOIT", "DONC", "DOS", "DROITE",
			"DÉBUT", "ELLE", "ELLES", "EN", "ENCORE", "ESSAI", "EST", "ET",
			"EU", "FAIT", "FAITES", "FOIS", "FONT", "FORCE", "HAUT", "HORS",
			"ICI", "IL", "ILS", "JE ", "LA", "LE", "LES", "LEUR", "LÀ", "MA",
			"MAINTENANT", "MAIS", "MES", "MINE", "MOINS", "MON", "MOT", "MÊME",
			"NI", "NOMMÉS", "NOTRE", "NOUS", "NOUVEAUX", "OU", "OÙ", "PAR",
			"PARCE", "PAROLE", "PAS", "PERSONNES", "PEUT", "PEU", "PIÈCE",
			"PLUPART", "POUR", "POURQUOI", "QUAND", "QUE", "QUEL", "QUELLE",
			"QUELLES", "QUELS", "QUI", "SA", "SANS", "SES", "SEULEMENT", "SI",
			"SIEN", "SON", "SONT", "SOUS", "SOYEZ", "SUJET", "SUR", "TA",
			"TANDIS", "TELLEMENT", "TELS", "TES", "TON", "TOUS", "TOUT",
			"TROP", "TRÈS", "TU", "VALEUR", "VOIE", "VOIENT", "VONT", "VOTRE",
			"VOUS", "VU", "ÇA", "ÉTAIENT", "ÉTAT", "ÉTIONS", "ÉTÉ", "ÊTRE",
			"Alors", "Au", "Aucuns", "Aussi", "Autre", "Avant", "Avec",
			"Avoir", "Bon", "Car", "Ce", "Cela", "Ces", "Ceux", "Chaque", "Ci",
			"Comme", "Comment", "Dans", "Des", "Du", "Dedans", "Dehors",
			"Depuis", "Deux", "Devrait", "Doit", "Donc", "Dos", "Droite",
			"Début", "Elle", "Elles", "En", "Encore", "Essai", "Est", "Et",
			"Eu", "Fait", "Faites", "Fois", "Font", "Force", "Haut", "Hors",
			"Ici", "Il", "Ils", "Je ", "La", "Le", "Les", "Leur", "Là", "Ma",
			"Maintenant", "Mais", "Mes", "Mine", "Moins", "Mon", "Mot", "Même",
			"Ni", "Nommés", "Notre", "Nous", "Nouveaux", "Ou", "Où", "Par",
			"Parce", "Parole", "Pas", "Personnes", "Peut", "Peu", "Pièce",
			"Plupart", "Pour", "Pourquoi", "Quand", "Que", "Quel", "Quelle",
			"Quelles", "Quels", "Qui", "Sa", "Sans", "Ses", "Seulement", "Si",
			"Sien", "Son", "Sont", "Sous", "Soyez", "Sujet", "Sur", "Ta",
			"Tandis", "Tellement", "Tels", "Tes", "Ton", "Tous", "Tout",
			"Trop", "Très", "Tu", "Valeur", "Voie", "Voient", "Vont", "Votre",
			"Vous", "Vu", "Ça", "Étaient", "État", "Étions", "Été", "Être",
 ]

};

jQuery(function() {
 jQuery.dynaCloud.stopwords = new RegExp("\\s((" + jQuery.dynaCloud.stopwords.join("|") + ")\\s)+", "gi");
 if (jQuery.dynaCloud.auto) {
  jQuery('.dynacloud').dynaCloud();
 }
});

jQuery.fn.dynaCloud = function(outElement) {
 var cloud = {};
 return this.each(function() {

  var cl = [];
  var max = 0;

  if (jQuery.wordStats && jQuery.dynaCloud.wordStats) {
   jQuery.wordStats.computeTopWords(jQuery.dynaCloud.max, this);
   for (var i = 0, j = jQuery.wordStats.topWords.length; i < j && i <= jQuery.dynaCloud.max; ++i) {
    var t = jQuery.wordStats.topWords[i].substring(1);
    if (typeof cloud[t] == 'undefined') {
     cloud[t] = { count: jQuery.wordStats.topWeights[i], el: t };
    }
    else {
     cloud[t].count += jQuery.wordStats.topWeights[i];
    }
    max = Math.max(cloud[t].count, max);
   }
   jQuery.wordStats.clear();
  }
  else {
   var elems = jQuery(this).text().replace(/[^A-Z\xC4\xD6\xDCa-z\xE4\xF6\xFC\xDF0-9_]/g, ' ').replace(jQuery.dynaCloud.stopwords, ' ').split(' ');
   var word = /^[a-z\xE4\xF6\xFC]*[A-Z\xC4\xD6\xDC]([A-Z\xC4\xD6\xDC\xDF]+|[a-z\xE4\xF6\xFC\xDF]{3,})/;

   jQuery.each(elems, function(i, n) {
    if (word.test(n)) {
     var t = n.toLowerCase();
     if (typeof cloud[t] == 'undefined') {
      cloud[t] = { count: 1, el: n };
     }
     else {
      cloud[t].count += 1;
     }
     max = Math.max(cloud[t].count, max);
    }
   });
  }

  jQuery.each(cloud, function(i, n) {
   cl[cl.length] = n;
  });

  if (jQuery.dynaCloud.sort) {
   cl.sort(function(a, b) {
    if (a.count == b.count) {
     return a.el < b.el ? -1 : (a.el == b.el ? 0 : 1);
    }
    else {
     return a.count < b.count ? 1 : -1;
    }
   });
  }

  var out;
  if ((out = jQuery(outElement ? outElement : '#dynacloud')).length == 0) {
   jQuery(document.body).append('<p id="dynacloud"><\/p>');
   out = jQuery('#dynacloud');
  }

  out.empty();

  var l = jQuery.dynaCloud.max == -1 ? cl.length : Math.min(jQuery.dynaCloud.max, cl.length);

  for (var i = 0; i < l; ++i) {
   out.append('<a href="#' + cl[i].el + '" style="font-size: ' + Math.ceil((cl[i].count / max) * jQuery.dynaCloud.scale) + 'em"><span>' + cl[i].el + '</span></a> &nbsp; ');
  }
  
  var target = this;

  jQuery('a', out).each(function() {
   jQuery(this).click(function() {

    if (jQuery.dynaCloud.single) {
     jQuery(document.body).removeHighlight();
    }

    var text = jQuery(this).text().toUpperCase();
    jQuery(target).each(function() {
     jQuery(this).highlight(text);
    });
    return false;
   });
  });

 });
};
