// Filtering of tagged DIV/SPAN tags on HTML page
// Copyright 2007 Gennadiy Shvets
// The program is distributed under the terms of the GNU General
// Public License 3.0
//
// To use this script:
// 1. [Optional] Change T_tag_size variable in this script if desired.
//
// 2. Add DIV tag below to your HTML page:
//
//		<div id="T_tags"></div>
//
// 3. Wrap parts of your page into DIV or SPAN tags:
//
//		<div class="_tags _tag1 _tag2">... your HTML code ...</div>
//
// 4. Add javascript to your HTML page
//
//		<script type="text/javascript" src="gs_tags.js"></script>
//
// See http://www.allmyscripts.com/Filtering_of_Tagged_Data/index.html for more
// information.

//	Set this variable to 1 if you want to adjust the size of tag text
//	depending on how common this tag is (rarely used tags are small,
//	the more often the tages are referenced the bigger they are).
var T_tag_size = 0;
//	Set this variable to 1 if you want to add "show all" / "hide all" links,
//	2 if you want to add "All" tag, or 0 if you don't want any additional tags
var T_add_all = 0;
//	This variable sets tagging mode: 0 (show selected) or
//	1 (hide selected).
var T_tag_mode = 0;

// ***** Do not change anything below this line *****

// Array of all DIV elements that have tagging data.
// This array is used to quickly switch display status of all DIVs
var T_all  = new Array ();
//	Array of all DIV element numbers broken down by tag name
//	Format: T_tags[tag_name] = Array of DIV element numbers that correspond to tag_name
//	Use T_all array to convert element number to real DIV/SPAN object.
var T_tags = new Array ();
// Array of all tag names. 
var T_tag_names = new Array ();
// This array contains display state of all tags.
// Format: T_tag_on[tag_name] = 0 (off) / 1 (on)
var T_tag_on = new Array ();
// Ths array maps tag_name to SPAN tag that is used to control appearence of
// tag name on the HTML page.
// Format: T_tag_span[tag_name] = span_object that corresponds to tag_name
var T_tag_span = new Array ();

function T_findTags (p_verbose)
{

	// Get div where all tags will be displayed
	var tags_div = document.getElementById('T_tags');
	if	(tags_div == null)
	{
		if	(p_verbose)
			alert ("DIV tag with id 'T_tags' not found!");
		return;
	}

	// Loop through all DIV and SPAN tags on the page
	T__processElements ('DIV');
	T__processElements ('SPAN');

	var all_len = T_all.length;
	//	Did we find at least one DIV?
	if	(all_len == 0)
	{
		if	(p_verbose)
			alert ("HTML page does not have DIV tags with tagging information!");
		return;
	}
	T_tag_names = T_tag_names.sort();
	var n_tags = T_tag_names.length;

	var i;
	var tag;
	var len;
	var min_len = all_len - 1;
	var max_len = 1;
	// Determine minimum/maximum number of DIV/SPAN elements per tag
	var html = (T_add_all)?
		'<a href="#" onClick="return T_showAll()" class="T_all">show all</a><a href="#" onClick="return T_hideAll()" class="T_all">hide all</a>': '';
	for (i = 0; i < n_tags; i++)
	{
		tag = T_tag_names[i];
		len = T_tags[tag];
		len = len.length;
		if	(len == all_len)  continue;
		if	(len < min_len)  min_len = len;
		if	(len > max_len)  max_len = len;
	}
	
	var avg = (max_len + min_len)/ 2;
	var diff = max_len - min_len;
	if	(diff == 0)  diff = 1;
	len = 100;
	//	Show HTML code
	var span_on = '';
	var span_off = (T_tag_size)? '</span>': '';
	for (i = 0; i < n_tags; i++)
	{
		tag = T_tag_names[i];
		len = T_tags[tag].length;
		// Don't show tag if it applies to all elements
		if	(len == all_len)
		{
			T_tag_names[i] = '';
			continue;
		}
		if	(T_tag_size)
			span_on = '<span style="font-size: ' +
				(parseInt (120 + ((len - avg)/ diff) * 50)) + '%">';
		html += '<a href="#" onClick="return T_showHide(\'' + i +
			'\')" id="T_tag_' + i + '" class="T_off">' + span_on +
			tag.replace(/ /g, '&nbsp;') + span_off + '</a> ';
	}
	tags_div.innerHTML = html;

	// Build an array that maps tag_name to SPAN object.
	for (i = 0; i < n_tags; i++)
	{
		tag = T_tag_names[i];
		T_tag_span[tag] = document.getElementById('T_tag_' + i);
	}
	tags_div.className = 'T_tags';

	if	(window.onload_gsl_tags)
		window.onload_gsl_tags();
}

function T__processElements (p_type)
{

	var array = document.getElementsByTagName(p_type);
	if	(array == null)  return;
	var cl;
	var one_el;
	var tag;
	var has_tags;
	var el_n = 0;
	for (var i = 0; i < array.length; i++)
	{
		one_el = array[i];
		cl = one_el.className;
		if	(!cl.match(/^_tags\s+/))  continue;
		var all_tags = cl.split(/\s+/);
		has_tags = 0;
		for (var j = 0; j < all_tags.length; j++)
		{
			tag = all_tags[j];
			if	(!tag.match(/^_/))  continue;
			if	(tag == '_tags')  continue;
			tag = tag.replace(/^_/, '');
			tag = tag.replace(/_/g, ' ');
			if	(T_tags[tag])
				T_tags[tag].push(el_n);
			else
			{
				//	Array(el_n) won't work when el_n is 0
				T_tags[tag] = new Array ();
				T_tags[tag].push(el_n);
				T_tag_on[tag] = 0;
				T_tag_names.push(tag);
			}
			has_tags = 1;
		}
		if	(has_tags)
		{
			T_all.push(one_el);
			el_n++;
		}
	}
}

function T_setMode (p_mode)
{
	T_tag_mode = p_mode;
	return T_showAll();
}

function T_showAll ()
{

	return T_showHideAll (0, 'block', 'T_off');
}

function T_hideAll ()
{
	return T_showHideAll (1, 'none', 'T_on');
}

function T_showHideAll (p_tag_on, p_display, p_class)
{

	var i;
	var obj;
	var tag;
	for (i = 0; i < T_tag_names.length; i++)
	{
		tag = T_tag_names[i];
		if	(tag == '')	continue;
		T_tag_on[tag] = p_tag_on;
		obj = T_tag_span[tag];
		if	(obj != null)
			obj.className = p_class;
	}

	for (i = 0; i < T_all.length; i++)
	{
		T_all[i].style.display = p_display;
	}

	return false;
}

function T_showHide (p_n)
{

	var tag = T_tag_names[p_n];
	if	(tag == null)  return false;
	var shown = T_tag_on[tag];
	var obj = T_tag_span[tag];
	if	(obj != null)
		obj.className = (shown)? 'T_off': 'T_on';
	T_tag_on[tag] = 1 - shown;

	var i;
	var div_state = new Array ();
	//	Set initial state for all DIV tags
	for (i = 0; i < T_all.length; i++)
	{
		div_state[i] = T_tag_mode;
	}

	var j;
	var el_n;
	var divs;
	//	Filtering is done differently depending on current mode
	if	(T_tag_mode)
	{
		//	If current mode is "hide selected" then we'll deselect all
		//	DIV elements that have at least one of their tags turned on
		for (i = 0; i < T_tag_names.length; i++)
		{
			tag = T_tag_names[i];
			if	(!T_tag_on[tag])	continue;
			divs = T_tags[tag];
			for (j = 0; j < divs.length; j++)
			{
				div_state[divs[j]] = 0;
			}
		}
	}
	else
	{
		var n_tags = 0;
		//	If initial state is "deselect all" then we're going to display only 
		//	elements that include all currently selected tags
		for (i = 0; i < T_tag_names.length; i++)
		{
			tag = T_tag_names[i];
			if	(!T_tag_on[tag])	continue;
			divs = T_tags[tag];
			for (j = 0; j < divs.length; j++)
			{
				div_state[divs[j]]++;
			}
			n_tags++;
		}

		for (i = 0; i < div_state.length; i++)
		{
			div_state[i] = ((!n_tags)||(div_state[i] == n_tags))? 1: 0;
		}
	}

	var state;
	//	Update state of all DIV tags
	for (i = 0; i < T_all.length; i++)
	{
		obj = T_all[i];
		state = (obj.style.display == 'none')? 0: 1;
		if	(div_state[i] != state)
			obj.style.display = (state)? 'none': 'block';
	}

	return false;
}

if	(window.onload)
    window.onload_gsl_tags = window.onload;
window.onload = T_findTags;

