User:Alex 21/script-episodetable.js

Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
$(function($) {
	setTimeout(function() {
		$.when( mw.loader.using( ['mediawiki.util']), $.ready ).then(function() {
			var portletlink = mw.util.addPortletLink('p-tv', '#', 'Episode table', '', 'CTRL+click to reset preset widths first');
			$(portletlink).click( function(e) {
				e.preventDefault();
				
				// Parameters
				var alltemplates = '';  var episodetables = []; var cellwidths = [];
				var vevent = document.getElementsByClassName('vevent');
				
				// Default widths noted by local consensus
				var defaultwidths = [];
				defaultwidths.overall = 5;
				defaultwidths.season = 5;
				defaultwidths.series = 5;
				defaultwidths.prodcode = 7;
				defaultwidths.viewers = 10;
				
				// Find episode tables
				for (var i = 0; i < vevent.length; i++) {
					if (vevent[i].classList[0] == 'vevent' && episodetables.indexOf(vevent[i].parentElement.parentElement) == -1)
						episodetables[episodetables.length] = vevent[i].parentElement.parentElement;
				}
				
				if (episodetables.length > 0) {
					for (i = 0; i < episodetables.length; i++) {
						// Particular episode table's header and its cells
						var episodetablerow = episodetables[i].rows[0];
						var hc = episodetablerow.cells;
						
						// Reset cell widths if holding down the CTRL key to be able to calculate optimum values for already-preset widths
						if (e.ctrlKey) {
							for (j = 0; j < hc.length; j++) {
								hc[j].style.width = '';
							}
						}
						
						// Calculating the displayed widths as percentages of each of the cells
						for (j = 0; j < hc.length; j++) {
							if (cellwidths[j] === undefined) cellwidths[j] = 0;
							var k_dw = false;
							for (var k in defaultwidths) {
								if (episodetable_cell(hc[j],k,1)) { cellwidths[j] += defaultwidths[k]; k_dw = true; }
							}
							if (!k_dw) cellwidths[j] += Math.round(100*hc[j].offsetWidth/episodetablerow.offsetWidth);
						}
					}
					
					// Calculate average widths of every corresponding cells, and total widths to 100%
					for (i = 0; i < cellwidths.length; i++) {
						cellwidths[i] = Math.round(cellwidths[i]/episodetables.length);
					}
					cellwidths = episodetable_total100(cellwidths,0);
					
					// Begin compiling template code
					for (i = 0; i < episodetables.length; i++) {
						var episodetable = episodetables[i];
						hc = episodetable.rows[0].cells;
						var template = "{{Episode table"; var templateT = ''; var templateR = '';
						var j = 0; var jv = -1;
						
						// Background colour
						var bgcolor = (hc[j].bgColor?hc[j].bgColor:RGBSTRtoHEX(hc[j].style.background?hc[j].style.background:hc[j].style.backgroundColor));
						var width = (episodetable.width?episodetable.width:episodetable.style.width);
						
						// Width, colour, caption
						if (width !== "" && width != "100%") template += " |total_width="+width.replace('%','');
						if (bgcolor != "#NANNANNAN") template += " |background="+bgcolor;
						if (episodetable.caption) template += " |caption="+episodetable_content(episodetable.caption,0);
						
						// No. overall
						if (episodetable_cell(hc[j],"title",0)) {
							template += " |overall="+episodetable_width(hc,j,'overall');
							templateT += " |overallT="+episodetable_content(hc[j],1);
							if (episodetable_ref(hc[j])) templateR += " |overallR=";
							j++;
						}
						// No. in series/season
						if (episodetable_cell(hc[j],"title",0)) {
							if (episodetable_cell(hc[j],"series",1)) {
								template += " |series="+episodetable_width(hc,j,'series');
								if (episodetable_ref(hc[j])) templateR += " |seriesR=";
							} else {
								template += " |season="+episodetable_width(hc,j,'season');
								templateT += " |seasonT="+episodetable_content(hc[j],1);
								if (episodetable_ref(hc[j])) templateR += " |seasonR=";
							}
							j++;
						}
						// Title
						if (true) {
							template += " |title="+episodetable_width(hc,j,0);
							templateT += " |titleT="+episodetable_content(hc[j],1);
							if (episodetable_ref(hc[j])) templateR += " |titleR=";
							j++;
						}
						// Aux1
						if (episodetable_cell(hc[j],"direct",0) && episodetable_cell(hc[j],"writ",0) && episodetable_cell(hc[j],"date",0)) {
							template += " |aux1="+episodetable_width(hc,j,0);
							templateT += " |aux1T="+episodetable_content(hc[j],1);
							if (episodetable_ref(hc[j])) templateR += " |aux1R=";
							j++;
						}
						// Director
						if (episodetable_cell(hc[j],"direct",1)) {
							template += " |director="+episodetable_width(hc,j,0);
							templateT += " |directorT="+episodetable_content(hc[j],1);
							if (episodetable_ref(hc[j])) templateR += " |directorR=";
							j++;
						}
						// Writer
						if (episodetable_cell(hc[j],"writ",1)) {
							template += " |writer="+episodetable_width(hc,j,0);
							templateT += " |writerT="+episodetable_content(hc[j],1);
							if (episodetable_ref(hc[j])) templateR += " |writerR=";
							j++;
						}
						// Aux2
						if (episodetable_cell(hc[j],"date",0) && episodetable_cell(hc[j],"release",0)) {
							template += " |aux2="+episodetable_width(hc,j,0);
							templateT += " |aux2T="+episodetable_content(hc[j],1);
							if (episodetable_ref(hc[j])) templateR += " |aux2R=";
							j++;
						}
						// Aux3
						if (episodetable_cell(hc[j],"date",0) && episodetable_cell(hc[j],"release",0)) {
							template += " |aux3="+episodetable_width(hc,j,0);
							templateT += " |aux3T="+episodetable_content(hc[j],1);
							if (episodetable_ref(hc[j])) templateR += " |aux3R=";
							j++;
						}
						// Air date
						if (episodetable_cell(hc[j],"date",1) || episodetable_cell(hc[j],"release",1)) {
							template += " |airdate="+episodetable_width(hc,j,0);
							if (episodetable_cell(hc[j],"release",1)) templateT += " |released=y";
							else templateT += " |airdateT="+episodetable_content(hc[j],1);
							if (episodetable_ref(hc[j])) templateR += " |airdateR=";
							j++;
						}
						// Alternate date
						if (episodetable_cell(hc[j],"date",1)) {
							template += " |altdate="+episodetable_width(hc,j,0);
							templateT += " |altdateT="+episodetable_content(hc[j],1);
							if (episodetable_ref(hc[j])) templateR += " |altdateR=";
							j++;
						}
						// Production code
						if (episodetable_cell(hc[j],"code",1)) {
							template += " |prodcode="+episodetable_width(hc,j,'prodcode');
							templateT += " |prodcodeT="+episodetable_content(hc[j],1);
							if (episodetable_ref(hc[j])) templateR += " |prodcodeR=";
							j++;
						}
						// Viewers
						if (episodetable_cell(hc[j],"viewers",1)) {
							template += " |viewers="+episodetable_width(hc,j,'viewers'); jv = j;
							if (episodetable_ref(hc[j])) templateR += " |viewersR=";
							j++;
						}
						// Aux4
						if (hc[j]) {
							template += " |aux4="+episodetable_width(hc,j,0);
							templateT += " |aux4T="+episodetable_content(hc[j],1);
							if (episodetable_ref(hc[j])) templateR += " |aux4R=";
							j++;
						}
						
						// Add comment to all reference parameters to restore the wikicode source
						// templateR = templateR.replace(/(\|[^\|\=]+=)/g, "$1<!--Be sure to restore the reference that existed here!-->");
						
						// Country of viewers
						if (jv != -1) {
							var country = episodetable_content(hc[jv],0).match(/(.*)\s*[V|v]iewers\s*(<br\ ?\/?>)?(\((.*)\))?/);
							if (country) {
								if (country[1]) template += " |country="+country[1].trim();
								if (country[4] && country[4].indexOf("million") == -1) template += " |viewers_type="+(country[4].replace("in ",""));
							}
						}
						
						// Compile template, template text, template references, and episodes
						template = template+templateT+templateR;
						template += " |episodes=";
						
						// Remove common variations of text
						var replace = ["|overallT=<br>overall", "|overallT=", "|overallT=No. in<br>series", "|seasonT=No. in<br>season", "|seasonT=in<br>season", "|seriesT=in<br>series", "|titleT=Title", "|directorT=Directed by", "|writerT=Written by", "|airdateT=Original air date", "|airdateT=Original release date", "|prodcodeT=<br>code", "|prodcodeT=Prod.<br>code", "|prodcodeT=Production<br>code"];
						for (var k = 0; k < replace.length; k++) template = template.replace(replace[k]+' |','|');
						
						// Done singular template
						alltemplates += template+"\n";
					}
					
					// Done all, and alert
					copyContent(alltemplates);
					alert("Episode table headers copied. Go to the editing page and replace the raw code, making sure you replace the ending |} with }}.");
				}
				
				// Calculate width of cells
				function episodetable_width(cells,j,type) {
					// If there's only one table, do not set widths.
					if (episodetables.length == 1) return "";
					
					var cell = cells[j];
					if (cell === undefined) return '';
					if (type != 0) cellwidths[j] = defaultwidths[type];
					cellwidths = episodetable_total100(cellwidths,j);
					var thiswidth = cellwidths[j].toString();
					cell.style.width = thiswidth+'%';
					return thiswidth;
				}
				
				// Determine if cell contains reference
				function episodetable_ref(cell) {
					if (cell === undefined) return false;
					return (cell.innerHTML.match(/<sup(.*)\/sup\>/g) ? true : false);
				}
				
				// Determine if cell innerHTML text contains text
				function episodetable_cell(cell,search,typesearch) {
					var io = episodetable_content(cell,0).toLowerCase().indexOf(search);
					return (typesearch === 0 ? io < 0 : io >= 0);
				}
				
				// InnerHTML content text of cell
				function episodetable_content(cell,stripall) {
					if (cell === undefined) return '';
					var reg = (stripall ? /<([^>]+?)([^>]*?)>(.*?)<\/\1>/ig : /<([^\>])*\>/g);
					return cell.innerHTML.replace(reg, '').replace("\n",'').trim();
				}
				
				// Total the widths to 100% by adding 1% to random cells
				function episodetable_total100(cellwidths,start) {
					function add(a, b) { return a + b; }
					var sum = cellwidths.reduce(add, 0);
					while (sum != 100) {
						var rand = Math.floor(Math.random()*(cellwidths.length-start)+start);
						cellwidths[rand] += (sum > 100 ? -1 : 1);
						sum = cellwidths.reduce(add, 0);
					}
					return cellwidths;
				}
			});
		});
	},100);
});